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

San*_*zor 2 evaluation haskell list lazy-evaluation fold

我无法理解以下原因:

foldr (\x y -> x && y) True [False,undefined,True]
Run Code Online (Sandbox Code Playgroud)

不是给我一个undefined例外。

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

关于它为什么返回的任何线索False

che*_*ner 6

它并没有undefinedundefined从未见过的那样无视。

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

foldr f z (x:xs) = f x (foldr f z xs)
Run Code Online (Sandbox Code Playgroud)

因此,经过一步,我们有

foldr (&&) True [False, undefined, True]
  == False && foldr (&&) True [undefined, True]
Run Code Online (Sandbox Code Playgroud)

因为False && _ == False,不需要评估对 的递归调用foldr,因此不需要对 做任何事情undefined


undefined仅在评估时引发异常。不需要评估它来定义 list [False, undefined, True],它是 的语法糖False : undefined : True : [],并且(:)它的第二个参数是惰性的。

  • 这是一个常见的误解,当我第一次看到这个时,它愚弄了我一分钟。但是“foldl”和“foldl”都“从”列表的“第一个”元素开始。名称中的“右”/“左”并不是指“从列表的哪一端开始”,而是指折叠功能如何关联。`foldr f acc [x,y,z]` 是 `fx (fy (fz acc))`,而具有相同参数的 `foldl` 是 `f (f (f acc x) y) z`。 (6认同)