使用as-pattern时非穷举模式

pee*_*ngh 2 haskell

我正在尝试使用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
Run Code Online (Sandbox Code Playgroud)

由于我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
Run Code Online (Sandbox Code Playgroud)

但是,这种方法现在给了我一个非详尽的模式错误.我不明白,我已经检查null accnull b,所以假设a不能为空.至于x,也没有在前面的方法中为它添加任何保护条款.

我有点迷失了我所缺少的模式.

Nei*_*etz 8

acc@(a:b)只会匹配非空列表.在@刚刚给出了值的别名,但图案仍需要匹配.

它好像你有这样的功能(虽然以更聪明的方式):

step x (a:b) = 
  let acc = (a:b) in
  ....
Run Code Online (Sandbox Code Playgroud)

step如果你打电话,你可以清楚地看到这里永远不会匹配step x []

回应评论:

step x null = [[x]]
Run Code Online (Sandbox Code Playgroud)

提供冗余匹配,因为它null是一个检查空列表的函数.它不是数据构造函数,因此在模式匹配中使用名称只是一个"通配符"(它总是匹配).您想匹配空数据构造函数[].

尝试:

step x [] = [[x]]
step x acc@(a:b)
  | null b = [[x]]
  | p x (head a) = (x:a):b
  | otherwise = [x]:acc
Run Code Online (Sandbox Code Playgroud)