Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 5,249
    • Issues 5,249
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 576
    • Merge requests 576
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell CompilerGlasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #4235
Closed
Open
Issue created Aug 02, 2010 by nestra@trac-nestra

deriving Enum fails for data instances

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?

Trac metadata
Trac field Value
Version 6.12.3
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler (Type checker)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking