为什么折叠包含未定义的列表时 foldr 不返回未定义?

Why is foldr not returning undefined when folding over a list containing undefined?

我无法理解以下原因:

foldr (\x y -> x && y) True [False,undefined,True]

不是 给我一个 undefined 异常。

我怎么看,foldr 比较 True 和列表的最后一个元素,即 True,因此返回 True,现在比较它至 undefined。如果涉及 undefined 类型,Haskell 是否会忽略该操作?我知道如果在匿名函数中我们有 x || y 而不是 (&&),那么输出是 True,因为编译器会看到其中一个运算符已经设置为 True,但由于我们正在使用 (&&),它必须检查两个值是否都设置为 True 或者其中一个设置为 False,对吗?

有什么线索可以解释为什么 returns False?

它并没有忽视 undefined,因为 undefined 从未见过。

foldr的真实定义稍微复杂一些,但我们可以假设它(部分)定义为

foldr f z (x:xs) = f x (foldr f z xs)

因此,一步之后,我们有

foldr (&&) True [False, undefined, True]
  == False && foldr (&&) True [undefined, True]

False && _ == False 以来,无需评估对 foldr 的递归调用,因此无需对 undefined.

执行任何操作

undefined 仅在 已计算 时引发异常。定义列表 [False, undefined, True] 不需要求值,它是 False : undefined : True : [] 的语法糖,而 (:) 在其第二个参数中是惰性的。

代码等同于

let {w = [head w,True]} in foldr (&&) True (False:w)
===
let {w = [head w,True] ; 
     r = foldr (&&) True w} in False && r
===
let {r=r} in False
===
False

foldr 如果组合函数在其第二个(右侧)参数中严格,则创建的计算仅处理右侧的输入列表。

这里(&&)不是。它是“短路”,如果它的第一个参数是 False,它会立即返回 False,因为它确实在这里。 r 永远不会被强制,因为不需要它的值。