haskell - Promoción de Data Constructor en GHC-7.6
(1)
Tenía este código:
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
que estaba compilando en GHC-7.4. Sin embargo, al pasar a GHC-7.6 comenzó a dar errores de compilación:
''And'' of tpe `forall tpe. tpe -> Symbol * tpe -> SSet tpe'' is not promotable
Al profundizar en los documentos, encontré una nueva cláusula añadida a las páginas de "Promoción de tipos de datos" en GHC-7.6 frente a GHC-7.4
No promovemos los tipos de datos cuyos constructores son polimórficos amables, implican restricciones o utilizan la cuantificación existencial.
Mi pregunta es:
- ¿Cuál es la razón detrás de no promover tales constructores?
- ¿Cuál sería la forma correcta de hacerlo?
No dijiste qué versión de GHC 7.6 estabas usando ni qué extensiones tienes, así que supongo un poco.
Este boleto parece responder a su pregunta 1, aunque no entiendo totalmente el problema yo mismo. En su ejemplo particular, creo que SSet
no es promocionable porque uno de sus argumentos ( Symbol tpe
) es un tipo asociado que trae consigo la restricción SymbolSet
.
Si muevo Symbol
fuera de la clase, obtenemos el tipo promocionado, sin embargo, ahora obtenemos errores de desajuste:
{-# LANGUAGE DataKinds , TypeFamilies , GADTs , MultiParamTypeClasses #-}
class SymbolSet tpe where
-- data Symbol tpe :: *
data Symbol tpe :: *
-- ...
Puedo obtener todo el shebang para compilar agregando firmas de tipo a 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
Realmente no entiendo tu código, así que puede que no funcione para ti.