2013-07-15 5 views
5

Die Dokumentation für monad-control bietet ein Beispiel dafür, wie eine Instanz von MonadTransControl mit erstellen defaultLiftWith und defaultRestoreT. Das Beispiel ist für die folgenden newtype:MonadTransControl Beispiel für eine benutzerdefinierte Monade

newtype CounterT m a = CounterT {unCounterT :: StateT Int m a} 

Dieses Beispiel eingestellt werden, kann für jeden newtype zu arbeiten, der nur einen „elementaren“ monadisch Transformator (wie die, die von transformers oder mtl) definiert wird. Aber was ist mit dem Fall, wo der Stapel zwei "elementare" Transformatoren enthält? Zum Beispiel, wie können wir eine MonadTransControl Beispiel für so etwas wie folgt definieren:

newtype T m a = T {unT :: MaybeT (StateT Int m) a} 

Mein Problem ist, dass ich weiß nicht, wie die folgende Zeile

newtype StT CounterT a = StCounter {unStCounter :: StT (StateT Int) a} 

vom CounterT anpassen zu machen arbeite für meinen T Transformator. Insbesondere weiß ich nicht, was ich in die letzte Klammer setzen soll. Es erwartet etwas, das Art (* -> *) -> * -> * hat, aber ich kann so etwas nicht bilden.

Irgendwelche Ideen?

Antwort

3

Ich habe nicht in der Lage gewesen defaultLiftWith und defaultRestoreT wieder zu verwenden, aber an ihrem Quellcode suchen und etwas zwicken, Ich kam im folgenden:

newtype CounterT m a = CounterT {unCounterT :: MaybeT (StateT Int m) a} deriving (Monad) 

instance MonadTrans CounterT where 
    lift = CounterT . lift . lift 

instance MonadTransControl CounterT where 
    newtype StT CounterT a = StCounter {unStCounter :: StT (StateT Int) (StT MaybeT a)} 
    liftWith = \f -> 
     CounterT $ liftWith $ \run -> 
        liftWith $ \run' -> 
        f $ liftM StCounter . run' . run . unCounterT    
    restoreT = CounterT . restoreT . restoreT . liftM unStCounter 
+0

Danke, das funktioniert. Anscheinend ist es nicht möglich, dies mit 'defaultLiftWith' /' defaultRestoreT' zu tun. Vermutlich sind sie nur für einfache Fälle. Ich denke, ich werde 'MonadBaseControl' schließlich nicht benutzen. Es erscheint mir zu kompliziert und ich fürchte, dass sich die API in Zukunft ändern wird, was es schwerer macht, meinen Code beizubehalten. – safsaf32