有一个懒惰的地图吗? [英] Is there a lazy mapM?

查看:106
本文介绍了有一个懒惰的地图吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

乍一看,我认为这两个功能是一样的:

  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 启用第二个定义,或者至少有一个不需要显式递归?

解决方案

一个解决方案是使用 ListT ,列表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

这篇关于有一个懒惰的地图吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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