在monad变压器类型类中使用列表monad? [英] Use list monad inside monad transformer type classes?

查看:44
本文介绍了在monad变压器类型类中使用列表monad?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是创建一个使用ReaderT WriterT堆栈或RWS堆栈内的列表monad的函数.更一般而言,如何在mtl类型类(例如MonadReader,MonadWriter)中使用列表monad?

我为什么要这样做?此问题是开始Haskell 中的一种练习.它要求我使用包装基本列表monad的MonadReader和MonadWriter的功能.要检查该功能是否通用,请使用两个不同的monad [测试]所需的功能: ReaderT r(WriterT w [])a RWST rwsma ",因此该书暗示这是可能的.

我不知道如何告诉"编译器以使用列表monad.如果我使用 ask>> =电梯 ask>> ==电梯.我可以使2级堆栈( RWST [] )或3级堆栈( ReaderT WriterT [] )正常工作,但不能同时工作./p>

我的问题重点:

  pathImplicitStack'开始结束|开始==结束=告诉[结束]pathImplicitStack的开始结束=做(s0,e0)<-询问>> =抬起警卫$ s0 ==开始告诉[开始]pathImplicitStack的e0端 

此外,我想知道如何键入该函数.到目前为止,我最大的尝试是 pathImplicitStack':::(MonadReader [(Int,Int)] m,MonadWriter [Int] m,MonadPlus m)=>整数->整数->m()我知道这是不对的,列表monad可能丢失了.另外,我认为MonadPlus在类型签名中可能很有用,但我不确定.

这行代码: do(s0,e0)<-ask>> = lift 是给我带来麻烦的代码.我尝试了0、1和2部缆车,但均未成功.我想询问一个 [(Int,Int)] ,然后使用列表monad仅处理一个(Int,Int)(让清单monad为我尝试所有可能性).

作为练习的一部分,我需要能够使用以下两个函数(或非常相似的函数)调用 pathImplicitStack':

  pathImplicitRW :: [[(Int,Int)]->整数->整数->[[Int]]pathImplicitRW边缘开始结束= execWriterT rdr其中rdr = runReaderT(pathImplicitStack的起始端)边沿:: WriterT [Int] []()pathImplicitRWS :: [((Int,Int)]->整数->整数->[[Int]]pathImplicitRWS边缘开始end =地图snd exec其中exec = execRWST(pathImplicitStack的开始结束)边() 

这与我以前的问题有关:我如何在ReaderT内使用列表单子?

便于测试的整个文件:

  {-#语言FlexibleContexts#-}模块Foo在哪里导入Control.Monad.Reader导入Control.Monad.Writer导入Control.Monad.RWSgraph1 :: [(Int,Int)]graph1 = [(2013,501),(2013,1004),(501,2558),(1004,2558)]pathImplicitRW :: [[(Int,Int)]->整数->整数->[[Int]]pathImplicitRW边缘开始结束= execWriterT rdr其中rdr = runReaderT(pathImplicitStack的起始端)边沿:: WriterT [Int] []()pathImplicitRWS :: [((Int,Int)]->整数->整数->[[Int]]pathImplicitRWS边缘开始end =地图snd exec其中exec = execRWST(pathImplicitStack的开始结束)边()pathImplicitStack':::(MonadReader [[Int,Int)] m,MonadWriter [Int] m,MonadPlus m)=>整数->整数->[m()]pathImplicitStack的开始结束|开始==结束=告诉[结束]pathImplicitStack的开始结束=做(s0,e0)<-询问>> =抬起警卫$ s0 ==开始告诉[开始]pathImplicitStack的e0端 

修改

根据我尝试的John L的反馈

  pathImplicitStack':::(MonadReader [[Int,Int)](t []),MonadWriter [Int](t []),MonadPlus(t []),MonadTrans t)=>整数->整数->t []()pathImplicitStack的开始结束|开始==结束=告诉[结束]pathImplicitStack的开始结束=做(s0,e0)<-询问>> =抬起警卫$ s0 ==开始告诉[开始]pathImplicitStack的e0端 

但是正如他指出的那样,它只能与一个monad转换器一起使用以包装列表monad,即RSWT,并且不能与ReaderT WriterT一起使用.所以这不是我要寻找的解决方案.

解决方案

因此,在问题要求之内进行此操作的基本问题是,没有MTL库函数可以从列表monad中提升,该列表monad可以是任意级别下.但是,您可以作弊"一点:组合的 Monad MonadPlus 实例是从基础列表monad继承的,无论深度如何,您可以使用它来生成所需的操作:

 做(s0,e0)<-询问>> = msum.地图返回 

然后,类型签名中也出现错误,需要将其更改为:

  pathImplicitStack':::(MonadReader [(Int,Int)] m,MonadWriter [Int] m,MonadPlus m)=>整数->整数->米() 

实际上,第二个想法实际上并不是在作弊.它只是使用 MonadPlus API链接替代操作,而不是直接使用基础列表monad.

My goal is to create a function that uses the list monad inside either a ReaderT WriterT stack, or a RWS stack. More generally, how do I use the list monad inside mtl typeclasses such as MonadReader, MonadWriter?

Why am I trying to do this? This problem is an exercise in Beginning Haskell. It asks me to "use functionality from both MonadReader and MonadWriter wrapping the base list monad. To check that the function is general, use two different monads to [test] the requested functionality: ReaderT r (WriterT w []) a and RWST r w s m a" So the book implies this is possible.

I can't figure out how to 'tell' the compiler to use the list monad. If I use ask >>= lift or ask >>= lift . lift I can get either the 2 level stack (RWST []) or 3 level stack (ReaderT WriterT []) to work, but not both.

The focus of my question:

pathImplicitStack' start end | start == end = tell [end]
pathImplicitStack' start end =
  do  (s0, e0) <- ask >>= lift
      guard $ s0 == start
      tell [start]
      pathImplicitStack' e0 end

Additionally, I'd like to know how to type the function. My best attempt so far looks something like pathImplicitStack' :: (MonadReader [(Int, Int)] m, MonadWriter [Int] m, MonadPlus m) => Int -> Int -> m () I know this isn't right, the list monad is probably missing. Also, I think MonadPlus might be useful in the type signature, but I'm not quite sure.

This line: do (s0, e0) <- ask >>= lift is the one giving me trouble. I've tried 0, 1, and 2 lifts without success. I'd like to ask for a [(Int, Int)] and then use the list monad to process just a (Int, Int) (and let the list monad try all possibilities for me).

As part of the exercise, I need to be able to call pathImplicitStack' with both of these functions (or very similar functions):

pathImplicitRW :: [(Int, Int)] -> Int -> Int -> [[Int]]
pathImplicitRW edges start end = execWriterT rdr
  where rdr = runReaderT (pathImplicitStack' start end) edges :: WriterT [Int] [] ()

pathImplicitRWS :: [(Int, Int)] -> Int -> Int -> [[Int]]
pathImplicitRWS edges start end = map snd exec
  where exec = execRWST (pathImplicitStack' start end) edges ()

This is related to my previous question: How do I use list monad inside of ReaderT?

The whole file for easy testing:

{-# LANGUAGE FlexibleContexts #-}

module Foo where

import Control.Monad.Reader
import Control.Monad.Writer
import Control.Monad.RWS

graph1 :: [(Int, Int)]
graph1 = [(2013,501),(2013,1004),(501,2558),(1004,2558)]


pathImplicitRW :: [(Int, Int)] -> Int -> Int -> [[Int]]
pathImplicitRW edges start end = execWriterT rdr
  where rdr = runReaderT (pathImplicitStack' start end) edges :: WriterT [Int] [] ()

pathImplicitRWS :: [(Int, Int)] -> Int -> Int -> [[Int]]
pathImplicitRWS edges start end = map snd exec
  where exec = execRWST (pathImplicitStack' start end) edges ()

pathImplicitStack' :: (MonadReader [(Int, Int)] m, MonadWriter [Int] m, MonadPlus m) => Int -> Int -> [m ()]
pathImplicitStack' start end | start == end = tell [end]
pathImplicitStack' start end =
  do  (s0, e0) <- ask >>= lift
      guard $ s0 == start
      tell [start]
      pathImplicitStack' e0 end

edit

Based on John L's feedback I tried

pathImplicitStack' :: (MonadReader [(Int, Int)] (t []), MonadWriter [Int] (t []), MonadPlus (t []), MonadTrans t) => Int -> Int -> t [] ()
pathImplicitStack' start end | start == end = tell [end]
pathImplicitStack' start end =
  do  (s0, e0) <- ask >>= lift
      guard $ s0 == start
      tell [start]
      pathImplicitStack' e0 end

but as he pointed out, it can only be used with one monad transformer to wrap the list monad, i.e. RSWT, and is not usable with ReaderT WriterT. So this is not the solution I am looking for.

解决方案

So, the basic problem with doing this within the requirements of the question is that there is no MTL library function for lifting from a list monad that may be arbitrary levels down. However, you can "cheat" a bit: The MonadPlus instance for the combined Monad is inherited from the underlying list monad regardless of the depth, and you can use it to generate the needed action:

  do  (s0, e0) <- ask >>= msum . map return

There is then also an error in the type signature, which needs to be changed to:

pathImplicitStack' :: (MonadReader [(Int, Int)] m, MonadWriter [Int] m, MonadPlus m) => Int -> Int -> m ()

EDIT: Actually on second thought this is not actually cheating. It's just using the MonadPlus API for chaining alternative actions instead of using the underlying list monad directly.

这篇关于在monad变压器类型类中使用列表monad?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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