Opened 9 years ago

Closed 5 years ago

Last modified 2 years ago

#4896 closed bug (fixed)

Deriving Data does not work for attached code

Reported by: mitar Owned by:
Priority: low Milestone: 7.10.1
Component: Compiler Version: 7.1
Keywords: deriving Cc: mmitar@…, jpm@…, andres@…, dreixel
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: deriving/should_compile/T4896
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

I get the following error when I try to derive Data for the attached code:

Main.hs:17:66:
    Couldn't match expected type `Bar (D a b)'
                with actual type `t' a1 b1'
    Expected type: Maybe (c (Bar (D a b)))
      Actual type: Maybe (c (t' a1 b1))
    In the expression: gcast2 f
    In an equation for `dataCast2': dataCast2 f = gcast2 f

Attachments (1)

Main.hs (401 bytes) - added by mitar 9 years ago.

Download all attachments as: .zip

Change History (15)

Changed 9 years ago by mitar

Attachment: Main.hs added

comment:1 Changed 9 years ago by simonpj

Cc: jpm@… andres@… added

I had a quick look. The Data/Typeable instances for type families make my head hurt badly.

Two facts. Currently GHC generates a Data instance looking like this

instance (Typeable (Bar (D a b)), Data a, Data b) => Data (Bar (D a b))
    where
      dataCast2 f = gcast2 f 

That fails. But it passes if we said dataCast1 f = gcast1 f.

Secondly, we are generating too many Typeable instances. If you try

instance Foo (D a b) where
  data Bar (D a b) = B deriving( Typeable )

instance Foo [a] where
  data Bar [a] = C deriving( Typeable )

you get

    Duplicate instance declarations:
      instance Typeable1 Bar -- Defined at T4896.hs:36:34-41
      instance Typeable1 Bar -- Defined at T4896.hs:39:30-37

I'd like someone to work out a clear story for what should happen for Data and Typeable instances for data families. Then I could implement it. Pedro perhaps? Or Andres?

Simon

comment:2 Changed 9 years ago by dreixel

Let me sketch quickly how I think this should work. We have a type family T and a data family D:

type family T :: * -> *
type instance T Int = ()
...

data family D a
data instance D Int = DInt Float
...

Regarding the type family T, I don't think deriving instances makes much sense. We want typeOf (() :: T Int) == typeOf (), because T Int ~ (). The same goes for Data and any other class, I guess: we just use the instance of the synonym, if there is one, and complain if there isn't.

Data families are more interesting. For Typeable, I guess it is sensible to allow deriving at the declaration spot:

-- deriving instance Typeable1 D
-- Should generate
instance Typeable1 D where
  typeOf1 _ = mkTyConApp (mkTyCon "Test.D") []

Although I find the empty list above a bit suspicious, this seems to be similar to the instance given for lists as well, for instance. The Typeable instance follows automatically from this Typeable1 instance.

Data is another story. We certainly cannot derive anything at the declaration point, since we know nothing about the constructors. For each instance, however, we know something:

instance Data (D Int) where
  toConstr (DInt f) = dintConstr
  dataTypeOf _ = dDatatype
  gfoldl k z (DInt f) = z DInt `k` f
  gunfold k z c = case constrIndex c of
                    _ -> undefined -- what do we do here?

dintConstr :: Constr
dintConstr = mkConstr dDatatype "DInt" [] Prefix

dDatatype :: DataType
dDatatype = mkDataType "Test.D" [dintConstr] -- trouble!

But there is one major problem (which raises the two issues above in the derived code). In the datatype description dDatatype we have to list all the constructors, but the set of constructors of a data family is open, so we can't do this.

Interestingly, gfoldl doesn't seem problematic. So I guess there are three options here:

1) Allow deriving Data for data family instances filling out only gfoldl and throwing errors for the others.

2) Refuse to generate Data instances for data families, as this is not possible in general.

3) Redesign syb such that it allows such instances.

comment:3 Changed 9 years ago by igloo

Milestone: 7.2.1

comment:4 Changed 8 years ago by igloo

Milestone: 7.4.17.6.1
Priority: normallow

comment:5 Changed 7 years ago by igloo

Milestone: 7.6.17.6.2

comment:6 Changed 6 years ago by mojojojo

difficulty: Unknown

I found my way to this issue after getting a code as trivial as the following failing with "Duplicate instance declarations":

data family DF a
data instance DF Int = DFInt deriving (Typeable)
data instance DF Char = DFChar deriving (Typeable)

So what's the current status of the issue? Is this recognized as a bug or expected behaviour? Are there any workarounds?

comment:7 Changed 5 years ago by thoughtpolice

Milestone: 7.6.27.10.1

Moving to 7.10.1.

comment:8 Changed 5 years ago by thomie

Status: newinfoneeded

This is the error message with HEAD (7.9.20141125) for the example from the description.

Main.hs:17:66:
    Couldn't match type ‘t'0 a0’ with ‘Bar’
    Expected type: Maybe (c (Bar (D a b)))
      Actual type: Maybe (c (t'0 a0 (D a b)))
    In the expression: gcast2 f
    In an equation for ‘dataCast2’: dataCast2 f = gcast2 f
    When typechecking the code for  ‘dataCast2’
      in a derived instance for ‘Data (Bar (D a b))’:
      To see the code I am typechecking, use -ddump-deriv

And the error message for mojojojo's example from comment:6 with HEAD (see also #5863):

test.hs:5:40:
    Deriving Typeable is not allowed for family instances;
    derive Typeable for ‘DF’ alone
    In the data instance declaration for ‘DF’

test.hs:6:42:
    Deriving Typeable is not allowed for family instances;
    derive Typeable for ‘DF’ alone
    In the data instance declaration for ‘DF’

Is there still a problem here?

comment:9 Changed 5 years ago by mitar

I don't think that the question is what error message says, but that there should not be any errors and that GHC should know how to handle/compile this in the first place, no?

comment:10 Changed 5 years ago by simonpj

Cc: dreixel added
Test Case: deriving/should_compile/T4896

The error message for mojojojo is exactly right.

The error message from HEAD for the original example is actually a long-standing bug; quite a different one from the one originally reported. This code should compile.

Good catch, thank you Tomie! Patch coming.

Pedro, can you just check that I have done this right?

Simon

comment:11 Changed 5 years ago by Simon Peyton Jones <simonpj@…>

In 863854a3a490afd9e3ecf0da6294a3b078f4a6a1/ghc:

Fix another bug in deriving( Data ) for data families; Trac #4896

If we have

   data family D a
   data instance D (a,b,c) = ... deriving( Data )

then we want to generate

   instance ... => Data (D (a,b,c)) where
     ...
     dataCast1 x = gcast1 x

The "1" here comes from the kind of D.  But the kind of the
*representation* TyCon is

   data Drep a b c = ....

ie Drep :: * -> * -> * -> *

So we must look for the *family* TyCon in this (rather horrible)
dataCast1 / dataCast2 binding.

comment:12 Changed 5 years ago by dreixel

Looks good to me!

comment:13 Changed 5 years ago by thomie

Resolution: fixed
Status: infoneededclosed

comment:14 Changed 2 years ago by RyanGlScott

Keywords: deriving added
Note: See TracTickets for help on using tickets.