J’ai eu ce 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 ab where instance (SymbolSet tpe) => HasElem (And (Identity tpe) s) s instance (HasElem sset s) => HasElem (And sset s) s
qui compilait dans GHC-7.4. Cependant, en passant à GHC-7.6, il a commencé à donner des erreurs de compilation:
'And' of tpe `forall tpe. tpe -> Symbol * tpe -> SSet tpe' is not promotable
Après avoir parcouru les documents, j’ai trouvé une nouvelle clause ajoutée aux pages “Promotion du type de données” dans GHC-7.6 et GHC-7.4.
Nous ne promouvons pas les types de données dont les constructeurs sont de nature polymorphe, impliquent des contraintes ou utilisent une quantification existentielle.
- Quelles sont les utilisations pratiques d’un constructeur protégé?
- Le constructeur de la classe de base sera-t-il automatiquement appelé?
- Quels destructeurs sont exécutés lorsque le constructeur lance une exception?
- Quand le constructeur d’un atsortingbut personnalisé est-il exécuté?
- Meilleur moyen de gérer plusieurs constructeurs en Java
Ma question est:
Vous n’avez pas dit quelle version de GHC 7.6 vous utilisiez ou quelles extensions vous utilisiez, donc je devine un peu.
Ce ticket semble répondre à votre question 1, même si je ne comprends pas totalement le problème. Dans votre exemple particulier, je pense que SSet
n’est pas promotible car l’un de ses arguments ( Symbol tpe
) est un type associé qui entraîne la contrainte SymbolSet
.
Si je déplace Symbol
hors de la classe, nous obtenons le type promu, mais maintenant nous obtenons des erreurs de type incompatibles:
{-# LANGUAGE DataKinds , TypeFamilies , GADTs , MultiParamTypeClasses #-} class SymbolSet tpe where -- data Symbol tpe :: * data Symbol tpe :: * -- ...
Je peux rassembler tout le shebang en ajoutant des signatures aimables à 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
Je ne comprends pas vraiment votre code, ce qui peut ne pas fonctionner pour vous.