问题描述
乍一看,我认为这两个功能是一样的: firstM _ [] = return Nothing
firstM p(x:xs)= px>> = \ r - >如果r然后返回(只是x)else firstM p xs
firstM'p xs = fmap listToMaybe(mapM p xs)
但他们没有。特别是,只要第一个 p x
为真, firstM
就会停止。但是 firstM'
,因为 mapM
,需要评估整个列表。
是否有一个lazy mapM
启用第二个定义,或者至少有一个不需要显式递归?
一个解决方案是使用,列表monad变换器。这种类型交错副作用和结果,所以你可以偷看最初的元素,而无需首先运行整个计算。
下面是一个使用 ListT
:
import Control.Monad
导入限定ListT
firstM :: Monad m => (a - > Bool) - > [a] - > m(也许a)
firstM p = ListT.head。 mfilter p。 ListT.fromFoldable
At first glance I thought these two functions would work the same:
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)
But they don't. In particular, firstM
stops as soon as the first p x
is true. But firstM'
, because of mapM
, needs the evaluate the whole list.
Is there a "lazy mapM
" that enables the second definition, or at least one that doesn't require explicit recursion?
One solution is to use ListT
, the list monad transformer. This type interleaves side effects and results, so you can peek at the initial element without running the whole computation first.
Here's an example using ListT
:
import Control.Monad
import qualified ListT
firstM :: Monad m => (a -> Bool) -> [a] -> m (Maybe a)
firstM p = ListT.head . mfilter p . ListT.fromFoldable
这篇关于有一个懒惰的地图吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!