为什么折叠包含未定义的列表时 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
永远不会被强制,因为不需要它的值。
我无法理解以下原因:
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
永远不会被强制,因为不需要它的值。