Вы можете разрешить предупреждение в этом особом случае, выполнив следующее:
gb_groupBy p input = foldr step [] input
where
step item acc = case acc of
[] -> [[item]]
(xs:xss) -> if p (head xs) item
then (item:xs):xss
else [item]:acc
Тогда сопоставление с образцом будет завершено, и условие «невозможно» для пустого списка в начале аккумулятора вызовет ошибку времени выполнения, но не выдаст предупреждение.
Еще один способ взглянуть на более общую проблему неполных сопоставлений с образцами - это увидеть их как «запах кода», то есть указание на то, что мы пытаемся решить проблему неоптимальным, или не-Хаскельским способом и попробуйте переписать наши функции.
Реализация groupBy с помощью Foldr делает невозможным применение его к бесконечному списку, что является целью проектирования, которую функции Haskell List пытаются достичь везде, где это семантически целесообразно. Рассмотрим
take 5 $ groupBy (==) someFunctionDerivingAnInfiniteList
Если первые 5 групп ж.р. равенство конечно, ленивая оценка закончится. Это то, что вы не можете сделать на строго оцененном языке. Даже если вы не работаете с бесконечными списками, написание таких функций приведет к повышению производительности в длинных списках или позволит избежать переполнения стека, возникающего при оценке выражений типа
take 5 $ gb_groupBy (==) [1..1000000]
В List.hs groupBy реализован так:
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy eq (x:xs) = (x:ys) : groupBy eq zs
where (ys,zs) = span (eq x) xs
Это позволяет интерпретатору / компилятору оценивать только те части вычислений, которые необходимы для результата.
span дает пару списков, где первый состоит из (последовательных) элементов из заголовка списка, удовлетворяющих предикату, а второй - остальной части списка. Он также реализован для работы с бесконечными списками.