Problème lors du mélange des classes de type et les familles de type
-
25-09-2019 - |
Question
Ce code compile bien:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
TypeOperators, TypeSynonymInstances, TypeFamilies #-}
class Sel a s b where
type Res a s b :: *
instance Sel a s b where
type Res a s b = (s -> (b,s))
instance Sel a s (b->(c,a)) where
type Res a s (b->(c,a)) = (b -> s -> (c,s))
mais dès que j'ajoute le GHC prédicat R échoue:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
TypeOperators, TypeSynonymInstances, TypeFamilies #-}
class Sel a s b where
type Res a s b :: *
instance Sel a s b where
type Res a s b = (s -> (b,s))
class R a where
type Rec a :: *
cons :: a -> Rec a
elim :: Rec a -> a
instance Sel a s (b->(c,Rec a)) where
type Res a s (b->(c,Rec a)) = (b -> s -> (c,s))
se plaignant que:
Illegal type synonym family application in instance:
b -> (c, Rec a)
In the instance declaration for `Sel a s (b -> (c, Rec a))'
qu'est-ce que cela signifie et (surtout) comment puis-je résoudre ce problème?
Merci
La solution
Type familles sont à sens unique: vous pouvez étendre Rec a
à son type calculé, mais vous ne pouvez pas (uniquement) aller de l'expansion retour à Rec a
. Cela rend les applications de fonctions de type ne convient pas pour les signatures d'exemple, car ils ne peuvent jamais déclencher l'instance d'appliquer.
Vous pouvez essayer à la place:
instance Rec a ~ reca => Sel a s (b->(c,reca))
Cela signifie quelque chose d'autre: il dit tout b -> (c, reca)
de fonction est une instance, puis quand il a irrévocablement apparié, le compilateur vérifie que Rec a ~ reca
. Mais cela pourrait être assez bon pour ne veulent dans votre cas.
Autres conseils
Rec
est pas un constructeur de type; il est une fonction de type. Peut-être que vous pouvez l'utiliser que dans le type d'une valeur de définition de type, non pas dans une déclaration de classe? Je devine sauvagement ici; Je ne comprends pas toutes les règles pour les familles de type.
Je ne sais pas comment le résoudre, mais certaines choses à essayer les suivantes:
-
Débarrassez-vous de la classe Sel et définir simplement
type family Res a s b :: *
. Utiliseztype instance
à la place du mécanisme de la classe. -
Il est à peine possible que faire
Rec
de type injective en utilisantdata
va aider, mais je ne pense pas. -
Retour sur le plus petit nombre d'extensions de langage qui pourraient éventuellement travailler-il plus facile pour les autres de vous aider, et il pourrait aider le compilateur ainsi.
Cela signifie que vous n'êtes pas autorisé à utiliser les familles de type synomym lors de la déclaration des instances de type. Voir la section du manuel GHC "familles de type et d'instance déclarations".
La seule façon que vous pouvez le fixer est de factoriser afin de ne pas besoin d'une certaine manière.