Я думаю, что то, как вы это делаете, выглядит нормально, но функция groups
грязная - особенно то, как вы отбрасываете ровно 1 из элементов, которые не удовлетворяют p на каждом шаге, что может привести к тому, что ваш результат будет иметьвнутри много лишних пустых списков.(Это, конечно, не повлияет на takeUntil
, если хотя бы 1 элемент a
удовлетворяет p
, но они все еще там.)
Я бы переписал groups
следующим образом, используя некоторыеполезные функции библиотеки:
groups p a = filter (p . head) $ groupBy ((==) `on` p) a
Я не знаю, является ли это более эффективным или нет, но я определенно считаю, что его легче читать.Чтобы пояснить, groupBy
(http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-List.html#v:groupBy) относится к Data.List
и разбивает список на список подсписков в зависимости от того, является ли функция из 2 последовательных аргументов истинной или нет. И on
(http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Function.html#v:on) - это небольшая удобная функция из Data.Function
, которая подает результат другой функции на входы двоичной функции. В результате
groupBy ((==) `on` p) a
разбивает список на секции, где p
всегда True
или всегда False
. Затем мы фильтруем это только по частям, которые являются Истиной.