Вы каждый раз " вращаете " 4-кортеж и переходите к первому элементу. Таким образом, мы можем реализовать это с помощью шаблона foldr
, который выглядит следующим образом:
toFour :: [a] -> ([a], [a], [a], [a])
toFour = foldr (<b>\a (bs, cs, ds, as) -> (a:as, bs, cs, ds)</b>) ([], [], [], [])
или с неопровержимым шаблоном:
toFour :: [a] -> ([a], [a], [a], [a])
toFour = foldr (\a <b>~(bs, cs, ds, as)</b> -> (a:as, bs, cs, ds)) ([], [], [], [])
Так что здесь (bs, cs, ds, as)
- это 4-кортеж, который мы сгенерировали для хвоста списка и «вращаем» вправо, чтобы создать кортеж (as, bs, cs, ds)
, а затем добавляем элемент a
к первому списку из четырех кортежей.
Для список целых чисел, это дает нам:
Prelude> toFour [1..2]
([1],[2],[],[])
Prelude> toFour [1..3]
([1],[2],[3],[])
Prelude> toFour [1..4]
([1],[2],[3],[4])
Prelude> toFour [1..5]
([1,5],[2],[3],[4])
Prelude> toFour [1..6]
([1,5],[2,6],[3],[4])
Prelude> toFour [1..10]
([1,5,9],[2,6,10],[3,7],[4,8])
Когда мы работаем с неопровержимым шаблоном, это делается лениво, поэтому мы можем, например, распределить элементы бесконечного списка, а затем, например, получить первый 10 элементов второго предмета:
Prelude> (\(_, l, _, _) -> take 10 l) (toFour [1..])
[2,6,10,14,18,22,26,30,34,38]