#4235: deriving Enum fails for data instances
-------------------------------+--------------------------------------------
    Reporter:  nestra          |       Owner:                                   
      
        Type:  bug             |      Status:  new                              
      
    Priority:  normal          |   Component:  Compiler (Type checker)          
      
     Version:  6.12.3          |    Keywords:  instance deriving, type 
families, GADTs
    Testcase:                  |   Blockedby:                                   
      
          Os:  Linux           |    Blocking:                                   
      
Architecture:  x86_64 (amd64)  |     Failure:  Compile-time performance bug     
      
-------------------------------+--------------------------------------------
 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?

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/4235>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to