1

前奏

foldl1:它获取列表的前两项并将函数应用于它们,然后将这个结果和第三个参数提供给函数,依此类推。

为什么不能写这样的东西?

foldl1 (==) [6, 6, 6]
foldl1 (\x y -> x == y) [6, 6, 6]
4

4 回答 4

5

如果要检查列表的所有元素是否相等,一个快速的解决方案是

allEqual [] = True --(edit: this case is not necessary as pointed out by sepp2k)
allEqual xs = all (== head xs) xs

我敢肯定,有人会写一个更优雅的方式来做到这一点,但这是有用的。

编辑:感谢 sepp2k 的建议。

于 2011-02-06T00:17:36.993 回答
2

编辑:Antal 指出我的推理不正确。这是评论的相关部分,它给出了真正的推理(我觉得这个逐字记录很糟糕,但这个答案被接受了,所以我不能删除它):

这不起作用的原因是类型foldl1(a -> a -> a) -> [a] -> a,但类型(==)Num a => a -> a -> Bool。由于Boolis not a Num(==)type 不匹配a -> a -> a,所以申请 offoldl1被拒绝。如果它被接受,你最终会遇到你试图做的情况True == 6,但类型系统一开始就永远不会让你走得那么远。

原始答案(后来的推理不正确):

==将需要两个Ints 并返回 a Bool。第一次迭代后,您的示例列表变为[True, 6]. 然后它尝试比较True哪个6失败。

于 2011-02-06T00:11:42.350 回答
1

这是另一个版本:

allEqual xs = and $ zipWith (==) xs (tail xs)
于 2011-02-06T18:29:27.503 回答
0

如果您想使用折叠,我建议您进行以下修改:

allEqual xs = foldr (\x acc -> x == head xs && acc) True xs

这与已经建议的方法非常相似all。请注意,这和all方法都可以在无限列表上工作(只要答案是False)。

对于非常长的有限列表,在极少数情况下,您可能会从严格的左折叠中获得更好的性能:

allEqual xs = foldl' (\acc x -> acc && x == head xs) True xs

但是对于这个问题,正确的折叠通常更好,因为(在这个实现中)它只执行等于 的折叠步骤length $ takeWhile (== head xs) xs。左length xs折叠每次都会执行折叠步骤。

于 2011-02-06T02:16:27.890 回答