Haskell 哈斯凯尔只想要一个答案

Haskell 哈斯凯尔只想要一个答案,haskell,fold,Haskell,Fold,当我只需要一个答案时,如何使折叠{l,r}终止 假设我有一个布尔值b1,b2,b3的列表,。。。我想把它们全部放在一起。如何使折叠在第一个真值时停止?它已经停止了!作为一个例子,让我们列一个清单 foo :: [Bool] foo = [False, False, False, True] ++ repeat False 其中,repeat只是生成一个无限列表,如果我们将其加载到GHCi中 *Main> foldr (||) False foo True “但是,但是怎么做?”你可

当我只需要一个答案时,如何使折叠{l,r}终止


假设我有一个布尔值b1,b2,b3的列表,。。。我想把它们全部放在一起。如何使折叠在第一个真值时停止?

它已经停止了!作为一个例子,让我们列一个清单

foo :: [Bool]
foo = [False, False, False, True] ++ repeat False
其中,
repeat
只是生成一个无限列表,如果我们将其加载到GHCi中

*Main> foldr (||) False foo
  True
“但是,但是怎么做?”你可能会想,哈斯克尔很懒,
foldr也很懒。如果您看一下实现,您会注意到它创建了如下内容

 foldr f a [b, c, d, e ... z] == (b `f` (c `f` (... (z `f` a)..)))
请注意,当您计算它时,如果
f
不需要右侧,它将不会被计算,并且我们可以忽略列表的整个其余部分,即使它是无限的。这在像Haskell这样的惰性语言中是可能的,因为我们只在需要的时候评估事物

|
的情况下,因为它被定义为

True  || _ = True
False || a = a
当左侧为true时,我们停止评估列表。免费短路


注意,
foldl
不共享这个好的属性,因为它涉及列表的所有元素。这就引出了一个很好的经验法则,如果你想要短路/非刚性,
foldr
通常是正确的选择,否则
foldl'
可能更快。

甚至比jozefg的答案还要短:在GHCi中尝试
或$repeat True
@LeftAroundaound,这只是因为前奏曲中定义的
或=foldr(| |)False
。由于某种原因,GHC实际上基于上下文递归地定义了它,这可能是为了实现特殊的or/构建优化。