我正在尝试使用文件夹实现自己的groupBy函数(类似于Prelude的函数)。
以下定义似乎可行:
myGroupBy p xs = foldr step [] xs
where step x acc
| null acc = [[x]]
| p x (head (head acc)) = (x:head acc):(tail acc)
| otherwise = [x]:acc
自从我多次使用head acc/tail acc
以来,尽管我可以通过使用as-pattern来改善它。所以我将其更改为:
myGroupByNew p xs = foldr step [] xs
where step x acc@(a:b)
| null acc = [[x]]
| null b = [[x]]
| p x (head a) = (x:a):b
| otherwise = [x]:acc
但是,此方法现在给我一个非穷尽的模式错误。我无法理解,我已经检查了null acc
和null b
,因此假设a
不能为null。至于x,也没有在前面的方法中为其添加任何保护子句。
我有点迷失了我所缺少的模式。
答案 0 :(得分:7)
acc@(a:b)
仅匹配非空列表。 @
只是为该值提供了别名,但是模式仍然需要匹配。
好像您具有这样的功能(尽管以一种更聪明的方式):
step x (a:b) =
let acc = (a:b) in
....
您可以在此处清楚地看到,如果您致电step
step x []
将永远不匹配
回复评论:
step x null = [[x]]
提供冗余匹配,因为null
是检查空列表的函数。它不是数据构造函数,因此在模式匹配中使用名称只是一个“通配符”(它始终匹配)。
您要匹配空数据构造函数[]
。
尝试:
step x [] = [[x]]
step x acc@(a:b)
| null b = [[x]]
| p x (head a) = (x:a):b
| otherwise = [x]:acc