known, I know: class contexts and mutual recursion

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

known, I know: class contexts and mutual recursion

Conor McBride
Hi folks

I just tripped over the "Contexts differ in length" error message. I
know it's not a new problem, but I thought I'd enquire as to its status.
For those of you who haven't seen it, here's an example, contrived but
compact.

 > data Thing
 >   = Val Int
 >   | Grok Thing (Maybe Int -> Int)

 > eval :: Monad m => Thing -> m Int
 > eval (Val i) = return i
 > eval (Grok t f) = return (f (eval t))

My eval function compiles ok. See? The recursive call to eval targets
the Maybe monad, so I get

*Mmm> eval (Grok (Val 5) (maybe 0 (1 +))) :: Maybe Int
Just 6

However, when I try to decompose eval as a pair of mutually recursive
functions, namely

 > foo :: Monad m => Thing -> m Int
 > foo (Val i) = return i
 > foo (Grok t f) = return (goo t f)

 > goo :: Thing -> (Maybe Int -> Int) -> Int
 > goo t f = f (foo t)

I get

Mmm.lhs:15:1:
   Contexts differ in length
   When matching the contexts of the signatures for
     foo :: forall (m :: * -> *). (Monad m) => Thing -> m Int
     goo :: Thing -> (Maybe Int -> Int) -> Int
   The signature contexts in a mutually recursive group should all be
identical

Poking about on the web, I got the impression that this was a known
infelicity in ghc 6.4 (which I'm using), due to be ironed out. However,
an early-adopting colleague with 6.6 alleges that foo-goo is still
poisonous. I'm wondering what the story is. I mean, is there some nasty
problem lurking here which prevents the lifting of this peculiar
restriction?

I'm not in a panic about this. I have a workaround for the problem as I
encountered it in practice. Mind you, it's the sort of thing that's
likely to happen more often, the more you localise the effects you tend
to use. In the above, goo doesn't throw exceptions; rather, because goo
has a handler, it can offer a /local/ exception-throwing capability to foo.

Curious

Conor

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: known, I know: class contexts and mutual recursion

Ian Lynagh
On Wed, Nov 29, 2006 at 06:14:56PM +0000, Conor McBride wrote:

>
> Mmm.lhs:15:1:
>   Contexts differ in length
>   When matching the contexts of the signatures for
>     foo :: forall (m :: * -> *). (Monad m) => Thing -> m Int
>     goo :: Thing -> (Maybe Int -> Int) -> Int
>   The signature contexts in a mutually recursive group should all be
> identical
>
> Poking about on the web, I got the impression that this was a known
> infelicity in ghc 6.4 (which I'm using), due to be ironed out. However,
> an early-adopting colleague with 6.6 alleges that foo-goo is still
> poisonous.

You can compile it with 6.6 if you use -fglasgow-exts. It's not clear to
me whether this will always work, e.g. if you have higher rank types
floating around, but if it does then we should add a hint to the error;
Simon?

> I'm wondering what the story is. I mean, is there some nasty
> problem lurking here which prevents the lifting of this peculiar
> restriction?

I don't know either, but this sounds like a good thing to bring up for
Haskell' if no-one has already.


Thanks
Ian

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: known, I know: class contexts and mutual recursion

Iavor Diatchki
In reply to this post by Conor McBride
Hello,

> I just tripped over the "Contexts differ in length" error message. I
> know it's not a new problem, but I thought I'd enquire as to its status.

I have run into that a number of times.  There aren't any technical
issues with solving it, in fact, depending on how one implements the
type checker, it is more work to implement this extra restriction
(Hugs and THIH don't impose this restriction).  The basic idea is that
we check values with explicit signatures after we have finished type
inference.  While we do type inference we may simply assume that the
values have their specified types.

It is proposed for fixing in Haskell' but I was surprised that it did
not seem to appear on the "definitely in" list (as far as I can
recall---I might be wrong).  Hopefully the report will be fixed
though.  Otherwise, as Ian mentioned, it works in GHC 6.6 with
-fglasgow-exts.  Also, there should be no problems with higher-ranked
types etc.

-Iavor



On 11/29/06, Conor McBride <[hidden email]> wrote:

> For those of you who haven't seen it, here's an example, contrived but
> compact.
>
>  > data Thing
>  >   = Val Int
>  >   | Grok Thing (Maybe Int -> Int)
>
>  > eval :: Monad m => Thing -> m Int
>  > eval (Val i) = return i
>  > eval (Grok t f) = return (f (eval t))
>
> My eval function compiles ok. See? The recursive call to eval targets
> the Maybe monad, so I get
>
> *Mmm> eval (Grok (Val 5) (maybe 0 (1 +))) :: Maybe Int
> Just 6
>
> However, when I try to decompose eval as a pair of mutually recursive
> functions, namely
>
>  > foo :: Monad m => Thing -> m Int
>  > foo (Val i) = return i
>  > foo (Grok t f) = return (goo t f)
>
>  > goo :: Thing -> (Maybe Int -> Int) -> Int
>  > goo t f = f (foo t)
>
> I get
>
> Mmm.lhs:15:1:
>    Contexts differ in length
>    When matching the contexts of the signatures for
>      foo :: forall (m :: * -> *). (Monad m) => Thing -> m Int
>      goo :: Thing -> (Maybe Int -> Int) -> Int
>    The signature contexts in a mutually recursive group should all be
> identical
>
> Poking about on the web, I got the impression that this was a known
> infelicity in ghc 6.4 (which I'm using), due to be ironed out. However,
> an early-adopting colleague with 6.6 alleges that foo-goo is still
> poisonous. I'm wondering what the story is. I mean, is there some nasty
> problem lurking here which prevents the lifting of this peculiar
> restriction?
>
> I'm not in a panic about this. I have a workaround for the problem as I
> encountered it in practice. Mind you, it's the sort of thing that's
> likely to happen more often, the more you localise the effects you tend
> to use. In the above, goo doesn't throw exceptions; rather, because goo
> has a handler, it can offer a /local/ exception-throwing capability to foo.
>
> Curious
>
> Conor
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: known, I know: class contexts and mutual recursion

Ross Paterson
In reply to this post by Ian Lynagh
On Mon, Dec 04, 2006 at 05:21:15PM +0000, Ian Lynagh wrote:

> On Wed, Nov 29, 2006 at 06:14:56PM +0000, Conor McBride wrote:
> >
> > Mmm.lhs:15:1:
> >   Contexts differ in length
> >   When matching the contexts of the signatures for
> >     foo :: forall (m :: * -> *). (Monad m) => Thing -> m Int
> >     goo :: Thing -> (Maybe Int -> Int) -> Int
> >   The signature contexts in a mutually recursive group should all be
> > identical
> >
> > Poking about on the web, I got the impression that this was a known
> > infelicity in ghc 6.4 (which I'm using), due to be ironed out. However,
> > an early-adopting colleague with 6.6 alleges that foo-goo is still
> > poisonous.
>
> You can compile it with 6.6 if you use -fglasgow-exts. It's not clear to
> me whether this will always work, e.g. if you have higher rank types
> floating around, but if it does then we should add a hint to the error;
> Simon?
>
> > I'm wondering what the story is. I mean, is there some nasty
> > problem lurking here which prevents the lifting of this peculiar
> > restriction?
>
> I don't know either, but this sounds like a good thing to bring up for
> Haskell' if no-one has already.

Haskell 98 mandates this behaviour: s4.5.2 says the types of all functions
in a dependency group must have the same context, even if they have
explicit signatures.

Haskell' ticket #65 (RelaxedDependencyAnalysis) proposes that dependencies
on variables with explicit signatures should be ignored by the dependency
analysis.  With that change, if you provided signatures for foo or goo,
or both, they'd be in different dependency groups and not required to
have the same context.  One could argue that this change should have
been made when polymorphic recursion was permitted.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: known, I know: class contexts and mutual recursion

Conor McBride
In reply to this post by Iavor Diatchki
Hi

Iavor Diatchki wrote:
> Hello,
>
>> I just tripped over the "Contexts differ in length" error message. I
>> know it's not a new problem, but I thought I'd enquire as to its status.
>
> I have run into that a number of times.  There aren't any technical
> issues with solving it, in fact, depending on how one implements the
> type checker, it is more work to implement this extra restriction

Yes, that's what I would expect. It's an inevitable but not threatening
consequence of polymorphic recursion. It rather surprised me that just
telling the machine what my plan was (something I always do anyway)
produced such an objection.

> It is proposed for fixing in Haskell' but I was surprised that it did
> not seem to appear on the "definitely in" list (as far as I can
> recall---I might be wrong).

 From what I can tell, it's "probably in". Strikes me as fairly
essential. I don't expect artificial restrictions to be placed on the
types of my programs when I am willing to make those types explicit.

>   Hopefully the report will be fixed
> though.  Otherwise, as Ian mentioned, it works in GHC 6.6 with
> -fglasgow-exts.  Also, there should be no problems with higher-ranked
> types etc.

Thanks for the tip, Ian. I guess I shouldn't put off installing 6.6 any
longer.

All the best

Conor

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

RE: known, I know: class contexts and mutual recursion

Simon Peyton Jones
In reply to this post by Ian Lynagh
| > Mmm.lhs:15:1:
| >   Contexts differ in length
| >   When matching the contexts of the signatures for
| >     foo :: forall (m :: * -> *). (Monad m) => Thing -> m Int
| >     goo :: Thing -> (Maybe Int -> Int) -> Int
| >   The signature contexts in a mutually recursive group should all be
| > identical
| >
| > Poking about on the web, I got the impression that this was a known
| > infelicity in ghc 6.4 (which I'm using), due to be ironed out. However,
| > an early-adopting colleague with 6.6 alleges that foo-goo is still
| > poisonous.
|
| You can compile it with 6.6 if you use -fglasgow-exts. It's not clear to
| me whether this will always work, e.g. if you have higher rank types
| floating around, but if it does then we should add a hint to the error;
| Simon?

Yes, it'll work in 6.6, and it's even documented (at the end of the section on type-system extensions).  I'll add a suggestion to the error message to use -fglasgow-exts

Simon

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe