来自前奏:
foldl1 :它需要前两项 列表并将函数应用于 他们,然后提供功能 这个结果和第三个论点和 等等。
为什么不能写这样的东西?
foldl1 (==) [6, 6, 6]
foldl1 (\x y -> x == y) [6, 6, 6]
答案 0 :(得分:5)
如果要检查列表中的所有元素是否相同,可以使用快速解决方案
allEqual [] = True --(edit: this case is not necessary as pointed out by sepp2k)
allEqual xs = all (== head xs) xs
我确信有人会写一种更优雅的方法来做到这一点,但这是可用的。
编辑:感谢sepp2k的建议。
答案 1 :(得分:2)
这不起作用的原因是foldl1
的类型为(a -> a -> a) -> [a] -> a
,但(==)
的类型为Num a => a -> a -> Bool
。由于Bool
不是Num
,(==)
类型与a -> a -> a
不匹配,因此foldl1
的申请被拒绝。如果它被接受了,你最终会遇到一个你试图做True == 6
的情况,但类型系统从来没有让你在第一时间走得那么远。
原始答案(后一种推理不正确):
==
将花费两个Int
并返回Bool
。第一次迭代后,您的示例列表变为[True, 6]
。然后,它会尝试将失败的True
与6
进行比较。
答案 2 :(得分:1)
这是另一个版本:
allEqual xs = and $ zipWith (==) xs (tail xs)
答案 3 :(得分: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
折叠步骤。