问题描述
我无法理解以下原因:
foldr (\x y -> x && y) True [False,undefined,True]
是不是给我一个undefined
例外。
我的看法是,foldr
比较 True
和列表的最后一个元素,即 True
,因此返回 True
,现在将其与 { 进行比较{1}}。如果操作涉及 undefined
类型,Haskell 会忽略它吗?如果在匿名函数中我们有 undefined
而不是 True
,我会理解输出是 x || y
,因为编译器会看到其中一个运算符已经设置为 {{1 }},但由于我们使用的是 (&&)
,因此必须检查两个值是否都设置为 True
或其中之一设置为 (&&)
,对吗?
关于它为什么返回 True
的任何线索?
解决方法
它并没有忽略 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,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
,因为不需要它的值。