作者:孜雪颖2000 | 来源:互联网 | 2022-12-02 18:10
我正在尝试使用foldr实现我自己的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
不能为空.至于x,也没有在前面的方法中为它添加任何保护条款.
我有点迷失了我所缺少的模式.
1> Neil Locketz..:
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