自定义monad的MonadTransControl实例 [英] MonadTransControl instance for a custom monad

查看:115
本文介绍了自定义monad的MonadTransControl实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

monad-control的文档提供了有关如何使用以下方法创建MonadTransControl实例的示例 defaultLiftWithdefaultRestoreT.该示例适用于以下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转换器(例如transformersmtl中的那些)定义的任何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}

中的

使其适用于我的T变压器.特别是,我不知道在最后一个括号中加上什么.它期望的是类似(* -> *) -> * -> *的东西,但是我无法形成类似的东西.

from the 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.

有什么想法吗?

推荐答案

我无法重用defaultLiftWithdefaultRestoreT,但是查看它们的源代码并稍作调整,我得出以下结论:

I haven't been able to reuse 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

这篇关于自定义monad的MonadTransControl实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆