Skip to content

Derived instances of Data lack dataCast1 and dataCast2

In the following code snippet:

data MyMaybe a = MyNothing | MyJust a deriving (Data, Typeable)

test1 :: ()
test1 = undefined `ext1Q` (\ (Just _) -> ()) $ Just ()

test1' :: ()
test1' = undefined `ext1Q` (\ (MyJust _) -> ()) $ MyJust ()

test1 evaluates to () as expected, but test1' evaluates to bottom.

The same happens for dataypes of kind * -> * -> *:

newtype Q r a = Q { unQ :: a -> r }
ext2Q :: (Data d, Typeable2 t)
      => (d -> q) -> (forall d1 d2. (Data d1, Data d2) => t d1 d2 -> q) -> d -> q
ext2Q def ext arg =
  case dataCast2 (Q ext) of
    Just (Q ext') -> ext' arg
    Nothing       -> def arg

data MyPair a b = MyPair a b deriving (Data, Typeable)

test2 :: ()
test2 = undefined `ext2Q` (\(_,_) -> ()) $ ((),())

test2' :: ()
test2' = undefined `ext2Q` (\(MyPair _ _) -> ()) $ MyPair () ()

test2 evaluates to () as expected, but test2' evaluates to bottom. Note that we need to define ext2Q, which uses dataCast2. ext1Q, which is defined in the library, uses dataCast1.

This happens because the derived Data instances for !MyMaybe and !MyPair are missing a definition for dataCast1 and dataCast2, respectively. The Data instances for Maybe and (,) are:

instance Data a => Data (Maybe a) where
  ...
  dataCast1 f  = gcast1 f

instance (Data a, Data b) => Data (a,b) where
  ...
  dataCast2 f  = gcast2 f
Trac metadata
Trac field Value
Version 6.10.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
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