Обратите внимание, что при использовании foldr
правые элементы данного списка будут обрабатываться первыми. Например, список:
[(0,2),(1,0),(1,2),(1,3),(1,4),(2,4)]
при обработке 3-го элемента (1,2)
, обработанные элементы, т.е. acc
acc = [[(1,3),(1,4)],[(2,4)]]
Итак, элемент нужно сравнить с (1,2)
, равным (1,3)
. это head (head acc)
не last (last acc)
. Более того, вместо использования head
к нему можно получить доступ через сопоставление с шаблоном:
(pairs@((x, y):xs):xss)
и сравнить с (a, b)
:
a == x && b == (y - 1)
и сгруппировать их, если выполняется условие:
((a, b):pairs):xss
Более того, более легко читаемо определить пошаговую функцию вместо использования анонимной функции, поскольку она должна обрабатывать самый правый элемент с пустым списком как:
step p [] = [[p]]
Как только первый элемент обработан, acc = [[p]]
и никогда не будет пустым списком на последующих шагах и, следовательно, будет соответствовать шаблону, определенному выше. Вот как определяется функция шага:
groupTogether = foldr step []
where step p [] = [[p]]
step p@(a, b) acc@(pairs@((x, y):xs):xss)
| a == x && b == (y - 1) = (p:pairs):xss
| otherwise = [p]:acc
Функция шага проста, если понять, как работает foldr
. Наконец, в качестве примечания, объявляем:
groupTogether [] = []
не обязательно. Поскольку foldr
вернет свой второй аргумент при передаче пустого списка в groupTogether
, в этом примере вернем []
.