DeriveFoldable rejects instances with constraints in last argument of data type
Currently, the -XDeriveFoldable extension will reject any derived Foldable instance for a data type where the last argument of the type constructor is constrained. For example, using this data type from TcDeriv.hs as inspiration:
{-# LANGUAGE DeriveFoldable, GADTs, StandaloneDeriving #-}
module DeriveFoldableRejected where
data T a b where
T4 :: Ord b => b -> T a b
T5 :: b -> T b b
T6 :: T a (b,b)
deriving instance Foldable (T a)
Compiling DeriveFoldableRejected.hs with GHC 7.10 will currently fail:
DeriveFoldableRejected.hs:9:1:
Can't make a derived instance of ‘Foldable (T a)’:
Constructor ‘T4’ must be truly polymorphic in the last argument of the data type
In the stand-alone deriving instance for ‘Foldable (T a)’
Failed, modules loaded: none.
I don't think this restriction needs to apply to Foldable instances. Unlike Functor and Traversable instances, which require the last argument to be truly universal, Foldable instances can get away without this. To demonstrate, here's a slightly modified T data type, without the constraints:
{-# LANGUAGE DeriveFoldable, GADTs, StandaloneDeriving #-}
{-# OPTIONS_GHC -ddump-deriv #-}
module DeriveFoldableLegal where
data T a b where
T45 :: b -> T a b
T6 :: T a b
deriving instance Foldable (T a)
The output of -ddump-deriv is:
Derived instances:
instance Data.Foldable.Foldable (DeriveFoldableLegal.T a_aDc) where
Data.Foldable.foldr f_aDd z_aDe (DeriveFoldableLegal.T45 a1_aDf)
= f_aDd a1_aDf z_aDe
Data.Foldable.foldr f_aDg z_aDh DeriveFoldableLegal.T6 = z_aDh
Data.Foldable.foldMap f_aDi (DeriveFoldableLegal.T45 a1_aDj)
= f_aDi a1_aDj
Data.Foldable.foldMap f_aDk DeriveFoldableLegal.T6
= GHC.Base.mempty
Copying this back into DeriveFoldableRejected.hs (after some cleanup):
{-# LANGUAGE DeriveFoldable, GADTs, StandaloneDeriving #-}
module DeriveFoldableRejected where
data T a b where
T4 :: Ord b => b -> T a b
T5 :: b -> T b b
T6 :: T a (b,b)
instance Foldable (T a) where
foldr f z (T4 a) = f a z
foldr f z (T5 a) = f a z
foldr f z T6 = z
foldMap f (T4 a) = f a
foldMap f (T5 a) = f a
foldMap f T6 = mempty
reveals that it will compile correctly with the generated code. Therefore, it seems like the check for universality in the last type argument shouldn't be used in -XDeriveFoldable.