如何在列表和 ListT monad 转换器之间干净地转换?
我目前正在编写一个项目,其中大量使用 ListT
monad 转换器。使用普通列表时,实现非确定性非常容易。然而,一旦我必须将代码转换为 ListT
,它就会变得更加复杂1。
举一个简单的例子:从 [a]
转换为 ListT a
实际上需要编写两个函数:
conv :: (Monad m) => [a] -> ListT m a
conv = ListT . return
虽然很简单,但我很惊讶它还没有实现。
问题:
- 是否有更好的方法来处理需要 monad 转换器的不确定性?
- 是否有任何技术/库可以在列表和 ListT 之间干净地来回转换?
1 具体原因很复杂,我不想过多阐述。
I am currently writing a project where I make a heavy use of ListT
monad transformer. When using plain lists, implementing nondeterminism is very easy. However once I had to convert my code to ListT
, it got much more complicated 1.
As a simple example: converting from [a]
to ListT a
actually requires composing two functions:
conv :: (Monad m) => [a] -> ListT m a
conv = ListT . return
Though it's simple, I am surprised it's not already there.
Questions:
- Is there some better way to handle nondeterminism where a monad transformer is needed?
- Are there any techniques / libraries for converting cleanly back and forth between lists and
ListT
?
1 The exact reasons are quite complicated, so I don't really want to elaborate too much on that.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不认为有任何图书馆可以做到这一点;毕竟,
conv
是一个极其简单的函数,而反过来就是runListT
。conv
类似于使用MaybeT
时经常需要的liftMaybe
:我建议将其命名为
liftList
>.1至于用于非确定性的更好的 monad 转换器,我建议查看 逻辑包,基于 Oleg 的 LogicT 转换器,它是一个基于连续的回溯逻辑 monad,具有 一些有用的操作。作为奖励,由于
[]
是MonadLogic
的实例,因此这些操作也适用于列表。1 有趣的是,我们可以定义一个函数来概括
conv
和liftMaybe
的模式:这可能会让您的代码非常混乱,所以我不这样做不建议使用它:)
I don't think there are any libraries for this;
conv
is an incredibly simple function, after all, and the other way around is justrunListT
.conv
is similar to theliftMaybe
often desired when usingMaybeT
:I would recommend naming it something along the lines of
liftList
.1As far as a better monad transformer for nondeterminism goes, I recommend taking a look at the logict package, based on Oleg's
LogicT
transformer, which is a continuation-based backtracking logic monad with some helpful operations. As a bonus, since[]
is an instance ofMonadLogic
, those operations also work on lists.1 Interestingly, we can define a function that generalises the pattern of
conv
andliftMaybe
:This will probably make your code quite confusing, so I don't recommend using it :)
几个月后我才遇到这个问题,因为我想知道类似的事情。所以我想出了以下方法:
到目前为止一切顺利 - 我的
ListT
/[]
对的joinT
方法看起来有一些东西与 ehird 的选择
有关。但这样做的问题是,单子转换器和单子之间实际上没有统一的接口,单子的行为被赋予了基本单子。我们有 MaybeT :: m (Maybe a) -> MaybeT m a 和
ListT :: m [a] -> ListT m a
,但是我们有StateT :: (s -> m (a, s)) -> StateT sm a。我不知道是否有办法解决这个问题——它肯定需要
I just came across this question a few months later because I was wondering something similar to this. So I came up with the following:
So far so good—and my
joinT
method for theListT
/[]
pair looks like it has something to do with ehird'schoose
.But the problem with this is that there is actually no uniform interface between a monad transformer and the monad whose behavior it endows to its base monad. We have
MaybeT :: m (Maybe a) -> MaybeT m a
andListT :: m [a] -> ListT m a
, but OTOH we haveStateT :: (s -> m (a, s)) -> StateT s m a
. I don't know if there's a way to get around this—it certaindly requires