[Haskell-cafe] SYB with class: Bug in Derive.hs module

Roman Cheplyaka roma at ro-che.info
Mon Sep 3 14:53:45 CEST 2012


* Andrea Vezzosi <sanzhiyan at gmail.com> [2012-09-03 12:50:03+0200]
> On Mon, Sep 3, 2012 at 12:00 PM, Roman Cheplyaka <roma at ro-che.info> wrote:
> > There's a bug in syb-with-class reported by Alexey Rodriguez Yakushev in
> > 2008 [1]. I can confirm that the bug is still there (syb-with-class-0.6.1.3,
> > ghc 7.4.1).
> >
> > [1]: http://www.haskell.org/pipermail/haskell-cafe/2008-March/041179.html
> >
> > Here's an even simpler test case:
> >
> >     {-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses,
> >         UndecidableInstances, TemplateHaskell, OverlappingInstances,
> >         DeriveDataTypeable #-}
> >     import Data.Generics.SYB.WithClass.Basics
> >     import Data.Generics.SYB.WithClass.Derive
> >
> >     data Foo = Foo Foo | Bar
> >       deriving (Typeable, Show)
> >
> >     deriveData [''Foo]
> >
> >     f :: (Data NoCtx ast, Typeable ast) => ast -> TypeRep
> >     f = typeOf
> >
> >     main = print $ f $ Foo Bar
> 
> This is pretty similar to what ended up being a ghc bug, fixed in 7.0 though:
> http://hackage.haskell.org/trac/ghc/ticket/3731

The difference between my test case and the one attached to the ticket
is that here there's an explicitly circular instance generated by TH.
In the "SYB with class" paper it is specifically said to be broken. So
it looks more like a problem in the TH code rather than in GHC.

> > The cause of this bug is a self-referencing instance created by
> > deriveData:
> >
> >     instance (Data ctx Foo, Sat (ctx Foo)) => Data ctx Foo where ...
> >
> > What's the proper way to fix it?
> 
> From a few tests it seems we no longer need the circular context hack
> in ghc-7.4.1 to get the instance to typecheck, so we could side-step
> the issue entirely by removing it from the generated code.

Not sure what hack you're referring to.

As I understand it, the circular context arises as a special case of the
context that includes all the "inner" types of a data type. It's not
possible to get rid of this context entirely — for example, consider

    data X a = X (Y a)

where we really need the "Data ctx (Y a)" context (but perhaps it could
be "Data ctx a" instead?).

So we need some criterion to decide whether a structural part of a data
type should be included into the instance context.

Does this make sense, or am I on the completely wrong track?

-- 
Roman I. Cheplyaka :: http://ro-che.info/



More information about the Haskell-Cafe mailing list