haskell - Haskell 守卫是按顺序评估的吗?
问题描述
评估 Haskell 守卫的顺序是什么?
假设我有一个返回 Bool 的函数:
someFunc :: Bool -> Bool -> Bool
someFunc b1 b2
| b1 == True && b2 == True = True
| b1 == True = False
| b1 == False .....
...
我认为这是我读到的 Monads 和 Do-notation,有时不会按顺序评估动作。那就是如果我有:
do { val1 <- action1
val2 <- action2
action3 }
可能会在 val1 之前计算 val2。
守卫也是这样吗?可以乱序评估它们吗?如果警卫是连续的,那么如果第一个语句的计算结果为 False,第二个语句的计算结果为 True,那么我可以得出 b2 为 False 的结论。这个逻辑总是成立吗?
编辑:通过陈述,我的意思是守卫 1 到 3
解决方案
评估守卫中的测试不会有任何副作用——与过程语言不同。因此,评估比较或布尔连接词的顺序对程序的语义没有任何影响。
优先级分支——即每一行开始|
——是从上到下。但真正的“评估”是错误的概念:编译器可以先评估您的b1 == False
,前提是它在检查前两个分支之前不采用第三个分支。(GHC 实际上并没有这样做;我只是在设置一个稻草人。)
请注意,在对 的调用中someFunc
, 的参数b1, b2
可能是任意复杂的表达式。Haskell 的“惰性语义”意味着在需要之前不会对它们进行评估。
这个逻辑总是成立吗?
请注意:如果早期守卫结果为 False,则您不能对其中的表达式做出任何假设。编译器可能已经重新排列它们以提高效率,不按文本顺序评估它们,然后继续。在您的示例中,如果结果是第一个分支b1 /= True
,编译器可能根本不会评估b2
。所以你不能得出任何关于b2
. 如果评估,确实b2
可能会给出底部/无限计算。
不仅仅是 Monads 或 Do-notation(它们是同一件事),表达式不一定按文本顺序进行评估——在任何上下文中的任何表达式中都是如此。(IO Monad 有一些狡猾的语义,使它看起来“语句”是从上到下执行的。)
推荐阅读
- amazon-web-services - 在pyspark中查找列表的最大值/最小值
- python - 卡住试图删除我的 print() 中的某些内容之间的空格
- python - 使用 Python 脚本在文件中查找和替换没有输出
- c# - CSVHelper - 可以写字典列表
- ffmpeg - 来自 rtsp ipcamera 的 FFmpeg 高效捕获
- node.js - 应用服务 Web 应用 SSO 集成和在重定向 URL 之前获取电子邮件名称
- pandas - 使用 dataframe.iloc 时,在同一数据帧的 2 列之间进行比较时返回什么?
- flutter - 按下 Tab 时自动滚动到 SliverList 项目之一
- azure - 如何使用 grub 使用 SLES 12 SP5 ISO 引导现有的 SLES 11 SP4
- python - 安装 Tensorflow Object Detection API 而不替换现有的 Tensorflow 包