Promotion du constructeur de données dans GHC-7.6

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.

Ma question est:

  1. Quelle est la raison de ne pas promouvoir de tels constructeurs?
  2. Quelle serait la bonne façon de le faire?

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.