5

文档monad-control提供了有关如何创建MonadTransControlusing defaultLiftWith和的实例的示例defaultRestoreT。该示例适用于以下内容newtype

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

可以调整此示例以适用于newtype仅使用一个“基本”monad 转换器定义的任何内容(例如来自transformersor的那些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变压器。特别是,我不知道在最后的括号中放什么。它期望有 kind 的东西(* -> *) -> * -> *,但我不能形成这样的东西。

有任何想法吗?

4

1 回答 1

3

我无法重用defaultLiftWithand defaultRestoreT,但是查看他们的源代码并稍微调整一下,我得出以下结论:

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
于 2013-07-15T23:22:45.517 回答