Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non exhaustive pattern while using as-pattern

Tags:

haskell

I am trying to implement my own groupBy function (similar to the Prelude's one) using foldr.

The following definition seems to work:

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

Since I was using head acc/tail acc in this multiple times, though I can improve it by using an as-pattern. So I changed this to:

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

However, this method now gives me a non-exhaustive pattern error. I cannot understand, I have checked for null acc and null b, so assuming a cannot be null. As for x, have not put any guard clause for it in the previous method too.

I am a bit lost what is the pattern that I am missing.

like image 454
peeyush singh Avatar asked Apr 01 '26 14:04

peeyush singh


1 Answers

acc@(a:b) will only ever match a non empty list. The @ just gives an alias for the value, but the pattern still needs to match.

its as if you have a function like this (albeit in a smarter way):

step x (a:b) = 
  let acc = (a:b) in
  ....

You can clearly see here that step doesn't ever match if you call step x []

Responding to the comment:

step x null = [[x]]

Gives a redundant match because null is a function that checks for the empty list. It is not a data constructor so using the name in the pattern match just is a "wildcard" (it always matches). You want to match the empty data constructor [].

try:

step x [] = [[x]]
step x acc@(a:b)
  | null b = [[x]]
  | p x (head a) = (x:a):b
  | otherwise = [x]:acc
like image 169
Neil Locketz Avatar answered Apr 04 '26 12:04

Neil Locketz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!