Skip to content

More informative error messages when closed type families fail to simplify

In the following code, I am getting strange compiler errors that I suspect has to do with the recursive application of the OrdRec type family:

import GHC.Prim
import Data.Proxy
import qualified Data.Set as Set

type family OrdRec (f :: * -> *) a b  :: Constraint where
    OrdRec f a (f b) = ( Ord a, Ord (f b), OrdRec f a b )
    OrdRec f a b = ( Ord a, Ord b ) 

setmap :: OrdRec Set.Set a b => (a -> b) -> Set.Set a -> Set.Set b
setmap f set = Set.map f set

GHC gives the error message:

ClosedTypeFamilyRecursion.hs:11:16:
    Could not deduce (Ord b) arising from a use of ‘Set.map’
    from the context (OrdRec Set.Set a b)
      bound by the type signature for
                 setmap :: (OrdRec Set.Set a b) =>
                           (a -> b) -> Set.Set a -> Set.Set b
      at ClosedTypeFamilyRecursion.hs:10:11-66
    Possible fix:
      add (Ord b) to the context of
        the type signature for
          setmap :: (OrdRec Set.Set a b) =>
                    (a -> b) -> Set.Set a -> Set.Set b
    In the expression: Set.map f set
    In an equation for ‘setmap’: setmap f set = Set.map f set
Failed, modules loaded: none.

If we modify the OrdRec type family to remove the recursive application:

type family OrdRec (f :: * -> *) a b  :: Constraint where
    OrdRec f a (f b) = ( Ord a, Ord (f b) )
    OrdRec f a b = ( Ord a, Ord b ) 

Then GHC is able to compile the file fine.

What's extra weird, though, is that ghci appears to be able to evaluate the recursive type family correctly. If we comment out the setmap function, then load into ghci, we can verify that the OrdRec type family is giving the correct Ord constraints:

ghci> :t Proxy :: Proxy (OrdRec [] Int Float)
Proxy :: Proxy (OrdRec [] Int Float) :: Proxy (Ord Int, Ord Float)

ghci> :t :t Proxy :: Proxy (OrdRec [] Int [Float])
Proxy :: Proxy (OrdRec [] Int [Float])
  :: Proxy (Ord Int, Ord [Float], (Ord Int, Ord Float))

ghci> :t Proxy :: Proxy (OrdRec [] Int [[Float]])
Proxy :: Proxy (OrdRec [] Int [[Float]])
  :: Proxy
       (Ord Int,
        Ord [[Float]],
        (Ord Int, Ord [Float], (Ord Int, Ord Float)))

But if I try to define the setmap function interactively in ghci, I get the same error message:

ghci> > let setmap = (\f set -> Set.map f set) :: OrdRec Set.Set a b => (a -> b) -> Set.Set a -> Set.Set b

<interactive>:39:25:
    Could not deduce (Ord b1) arising from a use of ‘Set.map’
    from the context (OrdRec Set.Set a b)
      bound by the inferred type of
               setmap :: (OrdRec Set.Set a b) =>
                         (a -> b) -> Set.Set a -> Set.Set b
      at <interactive>:39:5-98
    or from (OrdRec Set.Set a1 b1)
      bound by an expression type signature:
                 (OrdRec Set.Set a1 b1) => (a1 -> b1) -> Set.Set a1 -> Set.Set b1
      at <interactive>:39:14-98
    Possible fix:
      add (Ord b1) to the context of
        an expression type signature:
          (OrdRec Set.Set a1 b1) => (a1 -> b1) -> Set.Set a1 -> Set.Set b1
        or the inferred type of
           setmap :: (OrdRec Set.Set a b) =>
                     (a -> b) -> Set.Set a -> Set.Set b
    In the expression: Set.map f set
    In the expression:
        (\ f set -> Set.map f set) ::
          OrdRec Set.Set a b => (a -> b) -> Set.Set a -> Set.Set b
    In an equation for ‘setmap’:
        setmap
          = (\ f set -> Set.map f set) ::
              OrdRec Set.Set a b => (a -> b) -> Set.Set a -> Set.Set b
Trac metadata
Trac field Value
Version 7.8.2
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler (Type checker)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
Edited by Richard Eisenberg
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information