2013-07-15 7 views
5

la documentazione per monad-control fornire un esempio su come creare un'istanza di MonadTransControl utilizzando defaultLiftWith e defaultRestoreT. L'esempio è per il seguente newtype:esempio MonadTransControl per una monade personalizzato

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

Questo esempio può essere regolato per funzionare per qualsiasi newtype definito utilizzando un solo "elementare" trasformatore monade (come quelli di transformers o mtl). Ma per quanto riguarda il caso in cui lo stack contiene due trasformatori "elementari"? Ad esempio, come possiamo definire un'istanza MonadTransControl per qualcosa di simile:

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

mio problema è che non so come regolare la seguente riga

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

dal CounterT per renderlo lavoro per il mio trasformatore T. In particolare, non so cosa mettere nell'ultima parentesi. Si aspetta qualcosa che ha tipo (* -> *) -> * -> *, ma non riesco a formare nulla di simile.

Qualche idea?

risposta

3

non sono stato in grado di riutilizzare defaultLiftWith e defaultRestoreT, ma guardando il loro codice sorgente e tweaking leggermente, sono arrivato al seguente:

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

Grazie, che fa il lavoro. Apparentemente non è possibile farlo con 'defaultLiftWith' /' defaultRestoreT'. Presumibilmente sono solo per casi semplici. Penso che non userò mai "MonadBaseControl". Sembra troppo complicato e temo che in futuro l'API cambierà, rendendo più difficile mantenere il mio codice. – safsaf32