if-statement - 在单个 if 语句中使用 AND 评估组合的多个条件
问题描述
在诸如 C++ 之类的语言中,如果“if”语句中有多个条件,并且这些条件与使用 AND(即 &&)相结合,那么只要其中一个条件为假,后续条件的评估就不会发生。Haskell 也是这样吗?例如,在下面的 Haskell 代码中,条件 A 为 FALSE,会发生条件 B 的评估吗?
fun :: Haxl (Maybe Bool)
fun =
if conditionA .&& conditionB
then return $ Just True
else return Nothing
解决方案
这在 Haskell 中是正确的。&&
定义如下:
False && _ = False
True && y = y
这相当于以下内容:
(&&) x y = case x of
False -> False
True -> y
Haskell 中的惰性求值是这样定义的case
:当你对某事物进行模式匹配求值时,它会根据需要强制(求值)来确定要匹配的构造函数。所以这是自动短路。
这在 Haskell的任何地方都是如此。例如,foldr (&&) True [True, True, False, error "not reached"]
evaluates在评估后立即True && True && True && False && error "not reached"
返回,从不评估调用。False
False
error
此外,由于懒惰,在 Haskell 中,您始终可以将表达式分配给变量,并且不会改变计算的内容。例如,这些是完全等价的:
example1 x = cheapTest x || expensiveTest x
example2 x =
let
okay = cheapTest x
cool = expensiveTest x
in
okay || cool
-- or:
example2 x = okay || cool
where
okay = cheapTest x
cool = expensiveTest x
expensiveTest
除非被评估,否则不会被调用cool
,这只会在okay
is时发生False
。这与热切评估的语言不同,后者可能会改变运行时成本,也不同于非引用透明语言,后者可能会改变副作用。例如,在 JavaScript 中,example1
不同example2
的是:
function cheapTest(x) {
console.log('cheap test');
return x !== 0;
}
function expensiveTest(x) {
console.log('expensive test');
return Math.log2(x) < 10;
}
// Short-circuits second effect if possible.
function example1(x) {
return cheapTest(x) || expensiveTest(x);
}
// Always evaluates both effects.
function example2(x) {
var okay = cheapTest(x);
var cool = expensiveTest(x);
return okay || cool;
}
但是,您在haxl
包中显示的示例不是Haskell 标准库中的标准&&
运算符,而是使用了一个不同的自定义运算符,称为.&&
,其定义如下:
fa .&& fb = do a <- fa; if a then fb else return False
GenHaxl
因此,这是为库定义的自定义操作类型指定相同类型的短路。首先这个函数执行动作fa
,它产生一个Bool
被赋值的a
,然后只有当a
它True
执行下一个动作fb
。如果a
是False
,它只运行动作return False
(= pure False
),它不执行任何副作用并产生False
.
Haxl 还使用RebindableSyntax
扩展覆盖if
...<code>then...<code>else... 语法以允许条件中的副作用if
。在没有该扩展的普通 Haskell 代码中,您需要将效果与 分开if
,例如,在do
块中使用单独的绑定语句:
fun = do
c <- conditionA .&& conditionB
if c
then return $ Just True
else return Nothing
-- or: return $ if c then Just True else Nothing
推荐阅读
- c++ - 类似于 Knight-Tour-Problem 的回溯问题
- python - 为什么我在 if 语句中提出问题时会出现错误
- arduino - 在 if 语句中使用 & 运算符
- node.js - 从非 www 重定向到 www 域名后 cookie 丢失
- excel - 使用 vba-excel 从在线共享点文件夹下载 Zip 文件
- c# - 如何在 EF Core 5 Fluent API 中配置具有继承关系的值对象
- python - 有没有更好的方法来为深度嵌套的字典定义棉花糖模式?
- terminal - 如果我想在 Big Sur 上禁用 SIP,我可以 sudo 从 /System/Library/Desktop Pictures 中删除一些桌面背景图像怎么办?
- regex - 使用 PCRE2 库编译较少,--pattern='\$' 不起作用
- python - 搜索 MongoDB 数据库但 HTML 输入并在 webapp 上显示结果