2012-03-26 4 views
1

Ich möchte den Typ des Zustandsparameters eines Zustands-Monade-Transformators auf einen zugeordneten Typ dieses Monade-Transformators setzen. Dies führt jedoch eine unendliche Art bei der Konstruktion,haskell - Wie vermeidet man diesen unendlichen Typ? (Zugehörige Daten und StatusT)

s = AssocTyp (StateT s m) a 

Die Intuition, warum ist dies nicht wirklich ein Problem ist, dass,

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

für alle s und s'. Der Compiler ist jedoch nicht schlau genug, um das herauszufinden. Ich habe gelesen, dass in einigen Fällen ein neuer Typ verwendet werden kann, um unendliche Typen zu vermeiden; wie mache ich es?

Hier minimiert Code, um die Frage zu reproduzieren,

{-# 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) 

Antwort

2

Ich bin mir nicht sicher, was Sie erreichen wollen. die Gleichheit Sie jedoch feststellen,

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

ist nicht wahr, weil Sie eine Daten Familie eher als eine Art Familie verwenden. Der folgende Code kompiliert:

{-# 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 

Der Unterschied zwischen Typ Familien und Daten Familien ist, dass data families are injective, die folgende Implikation bedeutet hält, wenn DF Daten Familie ist:

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

Das ist nicht das, was Sie wollen in dein Fall.

+0

ah, vielen Dank !! Ich denke, ich verwechsle Gleichheit auf Typ- und Datenebene. – gatoatigrado

0

Nur für den Fall einer Daten Familie ist, was Sie wollen, ich habe eine Variante, die prüfen, nicht geben:

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

Entschuldigung, der 'isAssocType' wurde reduziert (zum Beispiel). – gatoatigrado

Verwandte Themen