>>> take 1 (subsequences undefined) [[]] >>> take 2 (subsequences ('a' : undefined)) ["","a"]
>>> subsequences "abc" ["","a","b","ab","c","ac","bc","abc"]This function is productive on infinite inputs:
>>> take 8 $ subsequences ['a'..] ["","a","b","ab","c","ac","bc","abc"]
map (take n) (take (product [1..n]) (permutations ([1..n] ++ undefined))) == permutations [1..n]
>>> permutations "abc" ["abc","bac","cba","bca","cab","acb"]
>>> permutations [1, 2] [[1,2],[2,1]]
>>> permutations [] [[]]This function is productive on infinite inputs:
>>> take 6 $ map (take 3) $ permutations ['a'..] ["abc","bac","cba","bca","cab","acb"]
>>> inits "abc" ["","a","ab","abc"]
>>> inits [] [[]]inits is productive on infinite lists:
>>> take 5 $ inits [1..] [[],[1],[1,2],[1,2,3],[1,2,3,4]]
>>> tails undefined [*** Exception: Prelude.undefined
>>> drop 1 (tails [undefined, 1, 2]) [[1, 2], [2], []]
>>> tails "abc" ["abc","bc","c",""]
>>> tails [1, 2, 3] [[1,2,3],[2,3],[3],[]]
>>> tails [] [[]]
>>> list [1,2,3] [[],[2,3],[1,3],[1,2]]
>>> list "abcd" ["","cd","ab","bcd","acd","abd","abc"]Note we always try the empty list first, as that is the optimal shrink.
>>> subsequences "abc" ["","a","b","ab","c","ac","bc","abc"]
>>> permutations "abc" ["abc","bac","cba","bca","cab","acb"]
Prelude> List.inits (0:1:2:undefined) [[],[0],[0,1]*** Exception: Prelude.undefinedThe following routine is more lazy than inits and even lazier than inits from utility-ht package, but it is restricted to infinite lists. This degree of laziness is needed for sqrtFP.
Prelude> lazyInits (0:1:2:undefined) [[],[0],[0,1],[0,1,2],[0,1,2,*** Exception: Prelude.undefined
>>> inits "abc" ["","a","ab","abc"]Note that inits has the following strictness property: inits (xs ++ _|_) = inits xs ++ _|_ In particular, inits _|_ = [] : _|_ inits is semantically equivalent to map reverse . scanl (flip (:)) [], but under the hood uses a queue to amortize costs of reverse.
>>> subsequences "abc" ["","a","b","ab","c","ac","bc","abc"]This function is productive on infinite inputs:
>>> take 8 $ subsequences ['a'..] ["","a","b","ab","c","ac","bc","abc"]
>>> permutations "abc" ["abc","bac","cba","bca","cab","acb"]The permutations function is maximally lazy: for each n, the value of permutations xs starts with those permutations that permute take n xs and keep drop n xs. This function is productive on infinite inputs:
>>> take 6 $ map (take 3) $ permutations ['a'..] ["abc","bac","cba","bca","cab","acb"]Note that the order of permutations is not lexicographic. It satisfies the following property:
map (take n) (take (product [1..n]) (permutations ([1..n] ++ undefined))) == permutations [1..n]
toTiers [x, y, z, ...] = [[x], [y], [z], ...]To convert back to a list, just concat.
>>> Comb.permute "abc" ["abc","acb","bac","bca","cab","cba"] >>> Comb.permute "aabc" ["aabc","aacb","abac","abca","acab","acba","aabc","aacb","abac","abca","acab","acba","baac","baca","baac","baca","bcaa","bcaa","caab","caba","caab","caba","cbaa","cbaa"]
QC.forAll (take 6 <$> QC.arbitrary :: QC.Gen [Int]) $ \xs -> allEqual $ map (\p -> sort (p xs)) $ Comb.permute : Comb.permuteFast : Comb.permuteShare : []