Haskell - 延迟评估是不是会导致此文件夹停止评估所有功能

Posted

技术标签:

【中文标题】Haskell - 延迟评估是不是会导致此文件夹停止评估所有功能【英文标题】:Haskell - Will lazy evaluation cause this foldr to stop evaulating all functionsHaskell - 延迟评估是否会导致此文件夹停止评估所有功能 【发布时间】:2020-01-23 00:37:50 【问题描述】:

func1, func2.. 都定义了 :: [String]-> Bool

一旦第一个 true 被命中,下面的折叠是否会停止评估函数

foldr (\x acc -> acc ||  x ) False ( fmap ($ "111") [func1,func2, func3, func4])

想一想,我意识到 fmap 将评估所有 4 个函数,然后将 [Bool] 传递给折叠......一旦它达到 True 就应该停止折叠。

我想我需要问的问题是,是否有办法将 fmap 合并到折叠中,以便在其中一个函数返回 true 时立即停止评估。

【问题讨论】:

您说“想一想我意识到 fmap 将评估所有 4 个函数,然后将 [Bool] 传递给折叠......一旦它达到 True 就应该停止折叠”。这是不真实的。仅仅因为它将[Bool] 传递给折叠,not 就意味着函数已被评估。他们会在需要时进行评估:如果您逐步完成纸上的评估,您可以自己了解何时发生这种情况。 【参考方案1】:

像你这样的功能

foldr (\x acc -> acc || x) False

已经为你写好了。它位于名称or 下的标准库中。请注意,它将参数的顺序翻转为(||),这是您想要的短路所必需的。因此,您可以将问题简化为

or . map ($ "111") $ fs

令人高兴的是,将函数映射到列表和or-ing 其结果的想法非常普遍:见证any。所以我们可以将你的整个表达式重写为

any ($ "111") fs

这样我们就不必担心细节了:写any 的人小心翼翼地没有对列表进行不必要的评估,所以从您的角度来看,这是一个已解决的问题。

【讨论】:

不,这不是or,因为它对|| 的参数是错误的。【参考方案2】:

您的foldr 函数使用了错误的||。你可能是想写:

foldr (\x acc -> x || acc) False

一旦你做出改变,不,不是所有的功能都会被评估。您可以通过Debug.Trace 亲自查看

main = print $ foldr (\x acc -> x || acc) False (fmap ($ True) [id, not, traceShowId, not])

这将只打印一个True,表明列表中的第三个函数不是强制的。

【讨论】:

以上是关于Haskell - 延迟评估是不是会导致此文件夹停止评估所有功能的主要内容,如果未能解决你的问题,请参考以下文章

是否有使用严格评估的 Haskell 编译器或预处理器?

Angular 中动态编译的延迟加载动态路由导致“不安全评估”错误

JOIN 子句中的 MySQL 逻辑评估是不是延迟/短路?

在 Haskell 中评估函数 a -> () 有啥规则?

具有haskell中的多参数函数的延迟过滤器

在Haskell中扩展数据类型