gadt changes in ghc 6.10

Jason Dagit dagit at
Tue Oct 14 22:31:54 EDT 2008

On Tue, Oct 14, 2008 at 6:37 PM, Daniel Gorín <dgorin at> wrote:

> On Oct 14, 2008, at 10:19 PM, Jason Dagit wrote:
> On Tue, Oct 14, 2008 at 7:27 AM, Daniel Gorín <dgorin at> wrote:
>> Hi
>> After installing ghc 6.10-rc, I have a program that no longer compiles. I
>> get the dreaded "GADT pattern match...." error, instead :)
>> Here is a boiled-down example:
> [...]
> I don't have 6.10 handy to try out your program, but in 6.8 and older the
> type error message you're getting means that the compiler needs more
> "outside in" help with type checking this.
> Usually this means adding type more type signatures on the outside.  For
> example, maybe you need to give the type signatures inside the case to make
> the types inside the pattern matches of the case more rigid.  That probably
> didn't make a lot of sense :(  So here is an example,
> case wit :: {- Try adding a signature here -} of ...
> Given that your code has such deep pattern nesting I would argue that it is
> in your best interest to add local functions (in a where clause) along with
> their explicit type signatures.  Start with the inner most case expressions
> and convert those to local functions and work your way out.
> I've tried adding some signatures (together with -XScopedTypeVariables),
>> but with no luck. Why is it that this no longer compiles? More importantly,
>> how can I make it compile again? :)
> I think adding local functions is easier than randomly sprinkling in the
> type signatures.  It has a nice side-effect that your new code is often
> easier to read as well.
> Good luck!
> Jason
> Thanks for the advice!
> By using some auxiliary functions I can now compile an alternative version
> of the program. And although the resulting program is more clear, I'd still
> like to know if this can be achieved be adding only annotations to the
> original program. The reason for this is that, for performance reasons,  I
> depend on the case-of-case transformation removing every possible case
> construct. I already verified this is happening for the original program and
> I rather keep the code as is than browse through the generated core again :)

It's unfortunate that you have such a situation with the optimizer.  How
often do you check that the optimizer is still smart enough?  It seems like
the sort of thing that could easily break between compiler releases.  If you
are going to depend on, I wonder if you could write a test to ensure that it
is happening every time.

> I must say that I also found this thread to be very helpful:

That is a good thread and it helped me a lot in the past too.  One of the
most important bits is when Simon says this:

GHC now enforces the rule that in a GADT pattern match
        - the type of the scrutinee must be rigid
        - the result type must be rigid
        - the type of any variable free in the case branch must be rigid

I would hypothesize that most people who encounter the message you're
getting fall into the last case, but I may be biased by my own experiences.

> <>
> I'll make sure the wiki points to it.

Oh, good idea!  Thanks!

> For the record the resulting code is this:
> {-# LANGUAGE GADTs, EmptyDataDecls #-}
> module T where
> data S
> data M
> data Wit t where
>     S :: Wit S
>     M :: Wit M
> data Impl t a where
>     I1 :: Maybe a -> Impl S a
>     I2 :: [a]     -> Impl M a
> type W_ t a = Wit t -> Impl t a
> newtype W t a = Wrap (W_ t a)
> unWrap1 :: Impl S a -> Maybe a
> unWrap1 (I1 m) = m
> unWrap2 :: Impl M a -> [a]
> unWrap2 (I2 m) = m
> bind :: W t a -> (a -> W t b) -> W_ t b
> bind (Wrap w) f = \wit ->
>     case wit of
>       S -> I1 $ do a <- unWrap1 (w S)
>                    case (f a) of
>                       Wrap w' -> unWrap1 (w' S)
>       M -> I2 $ do a <- unWrap2 (w M)
>                    case (f a) of
>                       Wrap w' -> unWrap2 (w' M)
My (untested) hunch is that, Wrap w', needs a type signature in your
original version.  I think this because of the 3rd case I mentioned above.
It would seem that your unWrap1 and unWrap2 fix the witness type, either S
or M.  Without playing with it (and again I don't have 6.10 handy), I'm not
sure which side of the arrow needs the type signature.  It could be that you
need something like:
Wrap (w' :: A type signature fixing M or S)

Or, you need it on the other side:
Wrap w' -> (w' :: some type sig) M

Either way, I think think the type t needs to be mentioned somewhere.

Good luck and let me know what you figure out, I'm quite curious now.
-------------- next part --------------
An HTML attachment was scrubbed...

More information about the Glasgow-haskell-users mailing list