是否有懒惰的mapM?

时间:2016-01-22 15:25:29

标签: haskell monads lazy-evaluation

乍一看,我认为这两个功能的作用相同:

firstM _ []     = return Nothing
firstM p (x:xs) = p x >>= \r -> if r then return (Just x) else firstM p xs

firstM' p xs    = fmap listToMaybe (mapM p xs)

但他们不是。特别是,只要第一个firstM为真,p x就会停止。但由于firstM'mapM需要对整个列表进行评估。

是否存在"懒惰mapM"启用第二个定义,或者至少一个不需要显式递归的定义?

3 个答案:

答案 0 :(得分:2)

一种解决方案是使用列表monad转换器ListT。这种类型会交叉副作用和结果,因此您可以先查看初始元素,而无需先运行整个计算。

以下是使用ListT的示例:

import Control.Monad
import qualified ListT

firstM :: Monad m => (a -> Bool) -> [a] -> m (Maybe a)
firstM p = ListT.head . mfilter p . ListT.fromFoldable

(请注意,ListTtransformers中定义的mtlbuggy,不应使用。我上面链接的版本应该没问题。)< / p>

答案 1 :(得分:1)

如果有,我怀疑它被称为mapM

我记得,mapM是根据sequence

定义的
mapM :: Monad m => (a -> b) -> [a] -> m [b]
mapM f = sequence . map f

并且sequence的重点是保证在给你任何东西之前完成所有的副作用。

与使用某些替代mapM相反,您只需使用mapsequence就可以逃脱,因此您可以将容器从[a]更改为{{1 }}:

Just a

甚至:

firstM p xs = sequence $ listToMaybe (map p xs)

现在firstM p xs = mapM f $ listToMaybe xs mapM可以对通用sequence进行操作,而不仅仅是列表。

答案 2 :(得分:1)

没有(不可能)安全,Monad - 多态懒惰mapM。但是the monad-loops package包含许多各种纯函数的惰性monadic变体,包括firstM