Здесь мы можем создать «вспомогательную функцию», которая для данного списка xs
генерирует список кортежей, где первый элемент - это выбранный нами элемент, а второй - список оставшихся элементов, например:
import Data.List(inits, tails)
pick :: [a] -> [(a, [a])]
pick ls = [(b, as ++ bs) | (as, (b:bs)) <- zip (inits ls) (tails ls)]
Например:
Prelude Data.List> pick [1..5]
[(1,[2,3,4,5]),(2,[1,3,4,5]),(3,[1,2,4,5]),(4,[1,2,3,5]),(5,[1,2,3,4])]
каждый элемент, таким образом, выбирает элемент из списка и возвращает список, в котором этот выбранный элемент удален.Мы можем использовать это, чтобы затем передать этот список следующему генератору.
Затем мы можем использовать это, например, в do
блоке, таком как:
perms :: (Num a, Enum a) => [(a, a, a, a, a, a, a)]
perms = do
(a, as) <- pick [1..7]
(b, bs) <- pick as
(c, cs) <- pick bs
(d, ds) <- pick cs
(e, es) <- pick ds
(f, [g]) <- pick es
return (a, b, c, d, e, f, g)
, что приводит к:
Prelude Data.List> perms
[(1,2,3,4,5,6,7),(1,2,3,4,5,7,6),(1,2,3,4,6,5,7),(1,2,3,4,6,7,5),(1,2,3,4,7,5,6),(1,2,3,4,7,6,5),(1,2,3,5,4,6,7),(1,2,3,5,4,7,6), ...