Глядя на определение span
в hackage , мы находим этот полезный совет:
span p xs эквивалентно (takeWhile p xs, dropWhile p xs)
Итак, как вы определили свою функцию как
group' [] = []
group' (x:xs) = (x : takeWhile (== x) xs) : group' (dropWhile (== x) xs)
Вы можете легко увидеть, что ваш p
в этом случае (== x)
. Итак, заменив его в определении диапазона выше
span p xs = (takeWhile p xs, dropWhile p xs)
span (== x) xs = (takeWhile (== x) xs, dropWhile (== x) xs)
span возвращает пару списков, поэтому вы можете получить к ним доступ с помощью fst
и snd
.
Итак, у нас есть это
takeWhile (== x) xs = fst (span (== x) xs)
и
dropWhile (== x) xs = snd (span (== x) xs)
Используя это, мы можем заменить их в исходной функции следующим образом:
group' [] = []
group' (x:xs) = (x : fst (span (== x) xs) ) : group' (snd (span (== x) xs) )
Конечно, нехорошо вызывать одну и ту же функцию с одинаковыми аргументами дважды (span (== x) xs
), поэтому давайте вызовем ее всего один раз с привязкой let
:
group' [] = []
group' (x:xs) = let s = span (== x) xs in (x : (fst s)) : group' (snd s)
Мне нравится, что Haskell в конце концов просто математика, и вы можете заменить некоторые определения (например, те, которые вы использовали с takeWhile и dropWhile) другими (span), используя только некоторые алгебраические уравнения!