自定义monad的MonadTransControl实例

时间:2013-07-15 11:54:41

标签: haskell monads monad-transformers

monad-control的文档提供了有关如何使用MonadTransControl创建实例的示例 defaultLiftWithdefaultRestoreT。该示例适用于以下newtype

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

此示例可以调整为适用于仅使用一个“基本”monad变换器(例如来自newtypetransformers的变换器)定义的任何mtl。但是堆栈包含两个“基本”变换器的情况又如何呢?例如,我们如何为这样的事物定义MonadTransControl实例:

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

我的问题是我不知道如何调整以下行

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

使其适用于我的T转换器。特别是,我不知道在最后一个括号中放什么。它期望有类似(* -> *) -> * -> *的东西,但我不能形成类似的东西。

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

我无法重复使用defaultLiftWithdefaultRestoreT,但查看其源代码并稍微调整一下,我得出以下结论:

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