20

最近一直困扰着我的一个快速问题。Haskell 是否在一个返回布尔值的函数中执行所有等价测试,即使返回一个错误值?

例如

f a b = ((a+b) == 2) && ((a*b) == 2)

如果第一个测试返回 false,它会在 ? 之后执行第二个测试&&?或者 Haskell 是否足够懒惰以至于不这样做并继续前进?

4

4 回答 4

24

应该像其他语言一样短路。在 Prelude 中是这样定义的:

(&&)                    :: Bool -> Bool -> Bool
True  && x              =  x
False && _              =  False

因此,如果第一个参数为 False,则永远不需要评估第二个参数。

于 2009-11-22T15:01:38.600 回答
5

就像马丁说的那样,具有惰性评估的语言永远不会评估任何不是立即需要的价值。在像 Haskell 这样的惰性语言中,你可以免费获得短路。在大多数语言中,|| 和 && 和类似的运算符必须专门内置到语言中,以使它们短路评估。然而,在 Haskell 中,惰性求值使得这变得不必要。您甚至可以定义一个使自己短路的函数:

scircuit fb sb = if fb then fb else sb

此函数的行为就像逻辑“或”运算符一样。这里是如何 || 在 Haskell 中定义:

True  || _ = True
False || x = x

因此,为了给您问题的具体答案,不。如果 || 的左侧 是真的,右手边永远不会被评估。对于“短路”的其他运算符,您可以将两个和两个放在一起。

于 2009-11-22T21:36:55.350 回答
2

正如 Caleb 所说,一个简单的测试来“证明”Haskell DO 有短路。

如果您尝试在无限列表上运行求和,您将得到堆栈溢出:

Prelude> foldr (+) 0 $ repeat 0
*** Exception: stack overflow

但是如果你(||)在无限列表中运行 eg (logical OR) on,你很快就会得到一个结果,因为短路:

Prelude> foldr (||) False $ repeat True
True
于 2021-01-07T13:52:07.040 回答
0

惰性评估意味着,在真正需要之前什么都不做。

于 2009-11-22T15:06:26.090 回答