Data Constructor promotion in GHC-7.6
I had this code:
class SymbolSet tpe where
data Symbol tpe :: *
data SSet tpe where
Identity :: tpe -> SSet tpe
And :: SSet tpe -> Symbol tpe -> SSet tpe
class HasElem a b where
instance (SymbolSet tpe) => HasElem (And (Identity tpe) s) s
instance (HasElem sset s) => HasElem (And sset s) s
which was compiling in GHC-7.4. However on moving to GHC-7.6 it started giving compilation errors:
'And' of tpe `forall tpe. tpe -> Symbol * tpe -> SSet tpe' is not promotable
on digging through the docs, I found a new clause added to "Datatype Promotion" pages in GHC-7.6 vs GHC-7.4
We do not promote datatypes whose constructors are kind polymorphic, involve constraints, or use existential quantification.
My question is:
- What is the rationale behind not promoting such constructors?
- What would be the correct way of doing it?
You didn't say which version of GHC 7.6 you were using or include which extensions you have on, so I'm guessing a bit.
This ticket seems to answer your question 1, although I don't totally understand the problem myself. In your particular example, I think SSet
isn't promotable because one of its arguments (Symbol tpe
) is an associated type which brings with it the SymbolSet
constraint.
If I move Symbol
out of the class we get the type promoted, however now we get kind mismatch errors:
{-# LANGUAGE DataKinds , TypeFamilies , GADTs , MultiParamTypeClasses #-}
class SymbolSet tpe where
-- data Symbol tpe :: *
data Symbol tpe :: *
-- ...
I can get the whole shebang to compile by adding kind signatures to HasElem
:
{-# LANGUAGE DataKinds , TypeFamilies , GADTs , MultiParamTypeClasses, FlexibleInstances #-}
class SymbolSet tpe where
-- MOVED OUT OF CLASS:
data Symbol tpe :: *
data SSet tpe where
Identity :: tpe -> SSet tpe
And :: SSet tpe -> Symbol tpe -> SSet tpe
-- ADDED KIND SIGNATURES:
class HasElem (a :: SSet *) (b :: Symbol *) where
instance (SymbolSet tpe) => HasElem (And (Identity tpe) s) s
instance (HasElem sset s) => HasElem (And sset s) s
I don't really understand your code so that may not work for you.