Problem with tuple with one element constrained

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Problem with tuple with one element constrained

Tyson Whitehead
I've been unable to get the following (simplified) code to be accepted by GHCi (8.0.1 and 8.0.2)

Prelude> let (x, y) = (1, return 2)
<interactive>:1:5: error:
    • Could not deduce (Monad m0)
      from the context: Num t
        bound by the inferred type for ‘x’:
                   Num t => t
        at <interactive>:1:5-24
      The type variable ‘m0’ is ambiguous
    • When checking that the inferred type
        x :: forall a (m :: * -> *) t. (Num a, Num t, Monad m) => t
      is as general as its inferred signature
        x :: forall t. Num t => t

and I don't seem to be able to provide a type signatures that GHCi is okay with

Prelude> let { x :: Int; y :: Monad m => m Int; (x, y) = (1, return 2) }
<interactive>:5:40: error:                                                                                                              
    • Ambiguous type variable ‘m0’                                                                                                      
      prevents the constraint ‘(Monad m0)’ from being solved.                                                                            
    • When checking that the inferred type                                                                                              
        x :: forall a (m :: * -> *) t (m1 :: * -> *).                                                                                    
             (Num a, Num t, Monad m) =>                                                                                                  
             t                                                                                                                          
      is as general as its signature                                                                                                    
        x :: Int                                                                                                                        

Prelude> let (x, y) = (1, return 2) :: (Int, Monad m => m Int)
<interactive>:4:31: error:
    • Illegal qualified type: Monad m => m Int
      GHC doesn't yet support impredicative polymorphism
    • In an expression type signature: (Int, Monad m => m Int)
      In the expression: (1, return 2) :: (Int, Monad m => m Int)
      In a pattern binding:                                                                                                              
        (x, y) = (1, return 2) :: (Int, Monad m => m Int)                                                                                

Prelude> let (x,y) = (1,return 2) :: Monad m => (Int, m Int)
<interactive>:7:5: error:
    • Ambiguous type variable ‘m0’
      prevents the constraint ‘(Monad m0)’ from being solved.
    • When checking that the inferred type
        x :: forall (m :: * -> *). Monad m => Int
      is as general as its inferred signature
        x :: Int

It seems the constraint on y leaks to x where it isn't well formed?  Any help and/or explanations would be greatly appreciated.  In my actual code the assignment is from the return value of a function so I can't just split it into two separate statements.

Thanks!  -Tyson
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Problem with tuple with one element constrained

Justus Adam
I am not sure really what you are trying to do, but here are a few
approaches which I think may solve your problem.

1. Calculate the monadic value outside or fmap over the tuple
constructor

for instance

do
x <- functionCall
return (y, x)

or

(y, ) <$> functionCall

(uses the TupleSections extension)

2. Use explicit forall and scoped type variables

If you really want to return a tuple with that monadic value from a
function then the `Monad m` constraint must be on the function itself.
Like so

Compiled with ExplicitForAll and ScopedTypeVariables

myFunction :: forall m. Monad m => m ...
myFunction =
  let
    x :: m SomeType
    (y, x) = (..., return ...)
  in ...

Which binds `m` to be of the same type as the outer `m`.

This is necessary as there must be some way that even from outside the
function we can figure out what concretely `m` actually is. Ergo it must
be bound in some way to the functions type signature.

3. ExistentialTypes

If you __really__ think you only need a `Monad` constraint on this type
(which I doubt) you can use an existential to wrap things into generic
monads.

(Uses ExistentialTypes)

data ExtMonad a = forall m. Monad m => ExtMonad m a



The thing I don't quite understand is, if you have a function call,
which produces the value, doesn't that call return a concrete monad?
Rather than just `Monad m`?

It sounds to me like you're actually barking up the wrong tree when you
try and do what you are doing here so I suggest using something like
approach 1 or 2 and perhaps rethinking if your problem may lay somewhere
else.

Regards

Justus

--
  Justus Adam
  [hidden email]

On Tue, Apr 18, 2017, at 12:41 PM, Tyson Whitehead wrote:

> I've been unable to get the following (simplified) code to be accepted by
> GHCi (8.0.1 and 8.0.2)
>
> Prelude> let (x, y) = (1, return 2)
> <interactive>:1:5: error:
>     • Could not deduce (Monad m0)
>       from the context: Num t
>         bound by the inferred type for ‘x’:
>                    Num t => t
>         at <interactive>:1:5-24
>       The type variable ‘m0’ is ambiguous
>     • When checking that the inferred type
>         x :: forall a (m :: * -> *) t. (Num a, Num t, Monad m) => t
>       is as general as its inferred signature
>         x :: forall t. Num t => t
>
> and I don't seem to be able to provide a type signatures that GHCi is
> okay with
>
> Prelude> let { x :: Int; y :: Monad m => m Int; (x, y) = (1, return 2) }
> <interactive>:5:40: error:                                                
>     • Ambiguous type variable ‘m0’                                        
>       prevents the constraint ‘(Monad m0)’ from being solved.            
>     • When checking that the inferred type                                
>         x :: forall a (m :: * -> *) t (m1 :: * -> *).                    
>              (Num a, Num t, Monad m) =>                                  
>              t                                                            
>       is as general as its signature                                      
>         x :: Int                                                          
>
> Prelude> let (x, y) = (1, return 2) :: (Int, Monad m => m Int)
> <interactive>:4:31: error:
>     • Illegal qualified type: Monad m => m Int
>       GHC doesn't yet support impredicative polymorphism
>     • In an expression type signature: (Int, Monad m => m Int)
>       In the expression: (1, return 2) :: (Int, Monad m => m Int)
>       In a pattern binding:                                              
>         (x, y) = (1, return 2) :: (Int, Monad m => m Int)                
>
> Prelude> let (x,y) = (1,return 2) :: Monad m => (Int, m Int)
> <interactive>:7:5: error:
>     • Ambiguous type variable ‘m0’
>       prevents the constraint ‘(Monad m0)’ from being solved.
>     • When checking that the inferred type
>         x :: forall (m :: * -> *). Monad m => Int
>       is as general as its inferred signature
>         x :: Int
>
> It seems the constraint on y leaks to x where it isn't well formed?  Any
> help and/or explanations would be greatly appreciated.  In my actual code
> the assignment is from the return value of a function so I can't just
> split it into two separate statements.
>
> Thanks!  -Tyson
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Problem with tuple with one element constrained

Sergiu Ivanov-2
In reply to this post by Tyson Whitehead

Hello Tyson,

Thus quoth  Tyson Whitehead  at 19:41 on Tue, Apr 18 2017:
>
> I've been unable to get the following (simplified) code to be accepted
> by GHCi (8.0.1 and 8.0.2)
>
> Prelude> let (x, y) = (1, return 2)
[...]
> and I don't seem to be able to provide a type signatures that GHCi is
> okay with

GHCi handles polymorphic types of interactive expressions somewhat
differently from the polymorphic types of expressions loaded from
files. (I'd be happy if someone could reproduce the explanation which I
saw a couple times but which I cannot find any more.)


Anyway, I put the following in tuple.hs:

func :: Monad m => (Int, m Int)
func = (1, return 2)

Then, ghci tuple.hs swallows the file no problem and allows me to do

*Main> func :: (Int, Maybe Int)
(1, Just 2)


(I have GHCi 8.0.2.)

--
Sergiu

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

signature.asc (497 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Problem with tuple with one element constrained

Tyson Whitehead
In reply to this post by Tyson Whitehead
On Tue, Apr 18, 2017, 16:02 Joshua Grosso <[hidden email]> wrote:
If I'm understanding correctly, GHCI's complaining about the fact that `return 2` requires it to create an instance of a `Monad`, but it doesn't know which `Monad` instance it should use...
Does `let (x, y) = (1, return 2) :: (Int, Maybe Int)` work (where you can replace `Maybe` with any other monad)?

Hi Joshua,

Thanks for the input. You are correct that if I choose a particular Monad instance GHCi accepts the code.

I believe it should be able to do the assignment without choosing one though. It is, for example, okay with let y = return 2.

I'm thinking Sergiu is onto something about this having to do with special GHCi handling.

Thanks! -Tyson


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Problem with tuple with one element constrained

Tyson Whitehead
In reply to this post by Sergiu Ivanov-2
Thanks Sergiu,

I know there was some defaulting, but didn't think much of it beyond that. Special GHCi handling makes sense. Maybe I'll open a ticket just in case this is an unintended effect.

Interesting observation about loading it from a file via typing it in.  My code is actually a test case for use with the doctest package that I was just running manually to work out.  I'm not sure if it does the equivalent of loading it from a file or not.

Ultimately I wound up doing the binding via a case statement instead of let.  It seems GHCi is okay with that.

Cheers!  -Tyon

On Tue, Apr 18, 2017, 17:01 Sergiu Ivanov <[hidden email]> wrote:
GHCi handles polymorphic types of interactive expressions somewhat
differently from the polymorphic types of expressions loaded from
files. (I'd be happy if someone could reproduce the explanation which I
saw a couple times but which I cannot find any more.)

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Problem with tuple with one element constrained

Sergiu Ivanov-2

Thus quoth  Tyson Whitehead  at 02:19 on Thu, Apr 20 2017:
>
> Interesting observation about loading it from a file via typing it in.

Initially I suspected the culprit was the monomorphism restriction being
turned off by default (:showi language in GHCi, (great thanks to Brandon
Allbery who mentioned this command on another thread)), but I don't
really see a difference when I turn it off.

> My code is actually a test case for use with the doctest package that
> I was just running manually to work out.  I'm not sure if it does the
> equivalent of loading it from a file or not.

Oh, I see.

> Ultimately I wound up doing the binding via a case statement instead
> of let.  It seems GHCi is okay with that.

That's kind of funny.  Seems somewhat inconsistent to my eye.

--
Sergiu

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

signature.asc (497 bytes) Download Attachment