id,summary,reporter,owner,description,type,status,priority,milestone,component,version,resolution,keywords,cc,os,architecture,failure,difficulty,testcase,blockedby,blocking,related
4235,deriving Enum fails for data instances,nestra,,"The following sample module does not compile:

{{{
{-# LANGUAGE TypeFamilies #-}
module Foo where

data family Foo a

data instance Foo Int
  = A | B
  deriving (Enum)
}}}

GHC gives 5 error messages, all to line 8 (the deriving clause), in terms of some internal representations of variables and types. I think that an error message should not be of this kind even if the code really contains an error. But here I even do not understand why the code should not be valid. In the case of deriving Eq, Ord, Bounded or Show for the same Foo Int, everything works fine; and also, old good instance declaration instead of deriving gives a normally working code. (Analogous errors are produced when deriving Ix.)

Here is the output of GHCi -v in the case of the above module (GHC gives a similar one):

{{{
Prelude> :l Foo
*** Chasing dependencies:
Chasing modules from:
Stable obj: []
Stable BCO: []
unload: retaining objs []
unload: retaining bcos []
Ready for upsweep []
Upsweep completely successful.
*** Deleting temp files:
Deleting:
*** Chasing dependencies:
Chasing modules from: *Foo.hs
Stable obj: []
Stable BCO: []
unload: retaining objs []
unload: retaining bcos []
Ready for upsweep
  [NONREC
      ModSummary {
         ms_hs_date = Mon Aug  2 14:30:44 UTC 2010
         ms_mod = main:Foo,
         ms_imps = []
         ms_srcimps = []
      }]
compile: input file Foo.hs
*** Checking old interface for main:Foo:
[1 of 1] Compiling Foo              ( Foo.hs, interpreted )
*** Parser:
*** Renamer/typechecker:

Foo.hs:8:12:
    Couldn't match expected type `Foo Int'
           against inferred type `Foo.R:FooInt'
      NB: `Foo' is a type function
    In the expression: Foo.$tag2con_R:FooInt ((+) (GHC.Types.I# a#) 1)
    In the expression:
        if (==) Foo.$maxtag_R:FooInt (GHC.Types.I# a#) then
            error
              ""succ{R:FooInt}: tried to take `succ' of last tag in enumeration""
        else
            Foo.$tag2con_R:FooInt ((+) (GHC.Types.I# a#) 1)
    In a case alternative:
        a#
          -> if (==) Foo.$maxtag_R:FooInt (GHC.Types.I# a#) then
                 error
                   ""succ{R:FooInt}: tried to take `succ' of last tag in enumeration""
             else
                 Foo.$tag2con_R:FooInt ((+) (GHC.Types.I# a#) 1)

Foo.hs:8:12:
    Couldn't match expected type `Foo Int'
           against inferred type `Foo.R:FooInt'
      NB: `Foo' is a type function
    In the expression: Foo.$tag2con_R:FooInt ((+) (GHC.Types.I# a#) -1)
    In the expression:
        if (==) 0 (GHC.Types.I# a#) then
            error
              ""pred{R:FooInt}: tried to take `pred' of first tag in enumeration""
        else
            Foo.$tag2con_R:FooInt ((+) (GHC.Types.I# a#) -1)
    In a case alternative:
        a#
          -> if (==) 0 (GHC.Types.I# a#) then
                 error
                   ""pred{R:FooInt}: tried to take `pred' of first tag in enumeration""
             else
                 Foo.$tag2con_R:FooInt ((+) (GHC.Types.I# a#) -1)

Foo.hs:8:12:
    Couldn't match expected type `Foo Int'
           against inferred type `Foo.R:FooInt'
      NB: `Foo' is a type function
    In the expression: Foo.$tag2con_R:FooInt a
    In the expression:
        if (&&) ((>=) a 0) ((<=) a Foo.$maxtag_R:FooInt) then
            Foo.$tag2con_R:FooInt a
        else
            error
              ((++)
                 ""toEnum{R:FooInt}: tag (""
                 (showsPrec
                    0
                    a
                    ((++)
                       "") is outside of enumeration's range (0,""
                       (showsPrec 0 Foo.$maxtag_R:FooInt "")""))))
    In the definition of `toEnum':
        toEnum a = if (&&) ((>=) a 0) ((<=) a Foo.$maxtag_R:FooInt) then
                       Foo.$tag2con_R:FooInt a
                   else
                       error
                         ((++)
                            ""toEnum{R:FooInt}: tag (""
                            (showsPrec
                               0
                               a
                               ((++)
                                  "") is outside of enumeration's range (0,""
                                  (showsPrec 0 Foo.$maxtag_R:FooInt "")""))))

Foo.hs:8:12:
    Couldn't match expected type `Foo Int'
           against inferred type `Foo.R:FooInt'
      NB: `Foo' is a type function
    In the first argument of `map', namely `Foo.$tag2con_R:FooInt'
    In the expression:
        map
          Foo.$tag2con_R:FooInt
          (enumFromTo (GHC.Types.I# a#) Foo.$maxtag_R:FooInt)
    In a case alternative:
        a#
          -> map
               Foo.$tag2con_R:FooInt
               (enumFromTo (GHC.Types.I# a#) Foo.$maxtag_R:FooInt)

Foo.hs:8:12:
    Couldn't match expected type `Foo Int'
           against inferred type `Foo.R:FooInt'
      NB: `Foo' is a type function
    In the first argument of `map', namely `Foo.$tag2con_R:FooInt'
    In the expression:
        map
          Foo.$tag2con_R:FooInt
          (enumFromThenTo
             (GHC.Types.I# a#)
             (GHC.Types.I# b#)
             (if (>) (GHC.Types.I# a#) (GHC.Types.I# b#) then
                  0
              else
                  Foo.$maxtag_R:FooInt))
    In a case alternative:
        b#
          -> map
               Foo.$tag2con_R:FooInt
               (enumFromThenTo
                  (GHC.Types.I# a#)
                  (GHC.Types.I# b#)
                  (if (>) (GHC.Types.I# a#) (GHC.Types.I# b#) then
                       0
                   else
                       Foo.$maxtag_R:FooInt))
*** Deleting temp files:
Deleting:
Upsweep partially successful.
*** Deleting temp files:
Deleting:
Failed, modules loaded: none.
}}}

Making deriving stand-alone does not help (the error messages would be more or less similar). It seems that the automatically derived code for methods is buggy and does not type-check.

Using GADTs also does not help, but the feedback is different. In the case of GADTs, (stand-alone) deriving does not work for other type classes either. For example, if the module is 

{{{
{-# LANGUAGE GADTs, StandaloneDeriving, FlexibleInstances #-}
module Foo where

data Foo a where
  A :: Foo Int
  B :: Foo Int

deriving instance (Eq (Foo Int))
}}}
then GHCi says the following:

{{{
Foo.hs:1:0:
    GADT pattern match in non-rigid context for `A'
      Probable solution: add a type signature for `Foo.$con2tag_Foo'
    In the pattern: A
    In the definition of `Foo.$con2tag_Foo': Foo.$con2tag_Foo A = 0#
}}}

Note the location of the error according to the message! 
Anyway, after deleting the stand-alone deriving, GHCi is satisfied. By the way, :i A then gives:

{{{
data Foo a where
  A :: (a ~ Int) => Foo Int
  ...
}}}

However, :t A gives:

{{{
A :: Foo Int
}}}

So, is the type system of GHC ambiguous? Why are the types given by :i and :t different?
",bug,closed,normal,7.0.1,Compiler (Type checker),6.12.3,fixed,"instance deriving, type families, GADTs",,Linux,x86_64 (amd64),Compile-time performance bug,,indexed-types/should_run/T4235,,,
