2012-03-26 3 views
1

Je souhaite définir le type du paramètre d'état, d'un transformateur de monadat d'état, sur un type associé de ce transformateur monad. Cependant, il en résulte la construction d'un type infini,haskell - Comment éviter ce type infini? (Données associées et étatT)

s = AssocTyp (StateT s m) a 

L'intuition pour expliquer pourquoi ce n'est pas vraiment un problème est que,

AssocTyp (StateT s m) a = AssocTyp (StateT s' m) a 

pour tous s et s'. Cependant, le compilateur n'est pas assez intelligent pour comprendre cela. J'ai lu que dans certains cas, un newtype peut être utilisé pour éviter les types infinis; Comment fait-on ça?

est ici le code réduit pour reproduire la question,

{-# LANGUAGE KindSignatures, TypeFamilies #-} 

import Control.Monad.Trans.State 

class MyMonad (m :: * -> *) where 
    data AssocTyp m :: * -> * 

instance MyMonad m => MyMonad (StateT s m) where 
    data AssocTyp (StateT s m) a = StateTA (AssocTyp m a) 

isAssocTyp :: Monad m => (AssocTyp m a) -> m() 
isAssocTyp x = return() 

x = do 
    v <- get 
    isAssocTyp (v) 

Répondre

2

Je ne sais pas ce que vous essayez d'atteindre. Cependant, l'égalité, vous dites,

AssocTyp (StateT s m) a = AssocTyp (StateT s' m) a 

est pas vrai, parce que vous utilisez un données famille plutôt que d'une famille de type . Le code suivant compile:

{-# LANGUAGE KindSignatures, TypeFamilies #-} 

import Control.Monad.Trans.State 

class MyMonad (m :: * -> *) where 
    type AssocTyp m :: * -> * 

instance MyMonad m => MyMonad (StateT s m) where 
    type AssocTyp (StateT s m) = AssocTyp m 

isAssocTyp :: Monad m => (AssocTyp m a) -> m() 
isAssocTyp x = return() 

x :: Monad m => StateT (AssocTyp m a) m() 
x = do 
    v <- get 
    isAssocTyp v 

La différence entre les familles des familles de type et données est que data families are injective, ce qui signifie l'implication suivante est si DF est la famille de données:

DF a b c = DF a' b' c' =====>  a = a', b = b', c = c' 

Ce n'est pas ce que vous voulez ton cas.

+0

ah, merci beaucoup !! Je pense que je mélange l'égalité au niveau du type et au niveau des données. – gatoatigrado

0

Juste au cas où une famille de données est ce que vous voulez, j'ai une variante de type ne vérifie:

isAssocType' :: (Monad m1, Monad m0) => (AssocTyp m1 a) -> m0() 
isAssocType' _ = return() 
+0

Désolé, le 'isAssocType' a été réduit (pour l'exemple). – gatoatigrado