一个一直困扰我的快速问题。 Haskell是否在返回布尔值的函数中执行所有等价测试,即使返回false值也是如此?
例如
f a b = ((a+b) == 2) && ((a*b) == 2)
如果第一个测试返回false,它会在&&
之后执行第二次测试吗?或者Haskell是否懒得不去做并继续前进?
答案 0 :(得分:19)
应该像其他语言一样短路。它在前奏中定义如下:
(&&) :: Bool -> Bool -> Bool
True && x = x
False && _ = False
因此,如果第一个参数为False,则永远不需要评估第二个参数。
答案 1 :(得分:5)
就像马丁所说,懒惰评估的语言永远不会评估任何不需要立即获得价值的东西。在像Haskell这样的懒惰语言中,您可以免费获得短路。在大多数语言中,||和&&并且必须专门为语言构建类似的操作符,以便对它们进行短路评估。但是,在Haskell中,懒惰的评估使得这不必要。你可以定义一个自己短路的功能:
scircuit fb sb = if fb then fb else sb
此函数的行为与逻辑“或”运算符类似。这是如何||在Haskell中定义:
True || _ = True
False || x = x
所以,为了给你问题的具体答案,没有。如果是||的左侧是的,右手边从未被评估过。您可以将两个和两个放在一起用于“短路”的其他操作员。
答案 2 :(得分:1)
懒惰评估意味着在真正需要之前不评估任何内容。
答案 3 :(得分:1)
一个简单的测试来“证明”Haskell DO 有短路,正如 Caleb 所说。
如果您尝试对无限列表进行求和,则会出现堆栈溢出:
GiftCard
但是如果你运行例如DOMAIN_EVENT_ENTRY
(逻辑或)在无限列表中,很快就会得到结果,因为短路:
Prelude> foldr (+) 0 $ repeat 0
*** Exception: stack overflow