自定义monad的MonadTransControl实例 [英] MonadTransControl instance for a custom monad
问题描述
monad-control
的文档提供了有关如何使用以下方法创建MonadTransControl
实例的示例
defaultLiftWith
和defaultRestoreT
.该示例适用于以下newtype
:
The docs for monad-control
provide an example on how to create an instance of MonadTransControl
using
defaultLiftWith
and defaultRestoreT
. The example is for the following newtype
:
newtype CounterT m a = CounterT {unCounterT :: StateT Int m a}
可以将本示例调整为适用于仅使用一个基本" monad转换器(例如transformers
或mtl
中的那些)定义的任何newtype
.但是,当堆叠中包含两个基本"变压器时,情况又如何呢?例如,我们如何为这样的事情定义MonadTransControl
实例:
This example can be adjusted to work for any newtype
that is defined using only one "elementary" monad transformer (such as the ones from transformers
or mtl
). But what about the case where the stack contains two "elementary" transformers? For example, how can we define a MonadTransControl
instance for something like this:
newtype T m a = T {unT :: MaybeT (StateT Int m) a}
我的问题是我不知道如何调整下一行
My problem is that I don't know how to adjust the following line
newtype StT CounterT a = StCounter {unStCounter :: StT (StateT Int) a}
使其适用于我的 from the 有什么想法吗? 我无法重用 I haven't been able to reuse 这篇关于自定义monad的MonadTransControl实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!T
变压器.特别是,我不知道在最后一个括号中加上什么.它期望的是类似(* -> *) -> * -> *
的东西,但是我无法形成类似的东西.CounterT
to make it work for my T
transformer. In particular, I don't know what to put in last parenthesis. It expects something that has kind (* -> *) -> * -> *
, but I cannot form anything like that.推荐答案
defaultLiftWith
和defaultRestoreT
,但是查看它们的源代码并稍作调整,我得出以下结论: defaultLiftWith
and defaultRestoreT
, but looking at their source code and tweaking it slightly, I arrived at the following: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