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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With