我目前正在编写一个我大量使用 ListT
的项目。单子(monad)变压器。使用普通列表时,实现非确定性非常容易。但是,一旦我不得不将我的代码转换为 ListT
,它变得更加复杂 1。
举个简单的例子:从 [a]
转换至ListT a
实际上需要组合两个函数:
conv :: (Monad m) => [a] -> ListT m a
conv = ListT . return
虽然它很简单,但我很惊讶它还没有。
问题:
ListT
之间干净利落地来回转换? ? 1 确切的原因很复杂,所以我真的不想过多阐述。
最佳答案
我认为没有任何图书馆可以解决这个问题。 conv
毕竟,这是一个非常简单的函数,而反过来只是 runListT
.conv
类似于 liftMaybe
使用 MaybeT
时经常需要:
liftMaybe :: (Monad m) => Maybe a -> MaybeT m a
liftMaybe = MaybeT . return
我建议将其命名为
liftList
.1就非确定性更好的单子(monad)更改器(mutator)而言,我建议看一下 logict包,基于 Oleg 的
LogicT
转换器,它是一个基于延续的回溯逻辑单子(monad),带有 some helpful operations .作为奖励,因为 []
是 MonadLogic
的一个实例,这些操作也适用于列表。1 有趣的是,我们可以定义一个泛化
conv
模式的函数。和 liftMaybe
:import Data.Foldable (Foldable)
import qualified Data.Foldable as F
choose :: (Foldable t, MonadPlus m) => t a -> m a
choose = F.foldr (\a b -> return a `mplus` b) mzero
这可能会让你的代码很困惑,所以我不建议使用它:)
关于list - 如何在列表和 ListT monad 转换器之间干净地转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9214829/