From cb9ff8bfa73fdfa1a38b609e878a52650dfdb682 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Wed, 15 Mar 2017 19:05:01 +0100 Subject: [PATCH] lib/lists: rename fold to foldr & improve fold docs In order to better distinguish foldr from foldl the default name is changed to foldr, but fold is still a synonym. Additionally the docs are improved and examples added. --- lib/lists.nix | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/lib/lists.nix b/lib/lists.nix index 5e224921de81..82d5ba0124cb 100644 --- a/lib/lists.nix +++ b/lib/lists.nix @@ -16,17 +16,22 @@ rec { */ singleton = x: [x]; - /* "Fold" a binary function `op' between successive elements of - `list' with `nul' as the starting value, i.e., `fold op nul [x_1 - x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'. (This is - Haskell's foldr). + /* “right fold” a binary function `op' between successive elements of + `list' with `nul' as the starting value, i.e., + `foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'. + Type: + foldr :: (a -> b -> b) -> b -> [a] -> b Example: - concat = fold (a: b: a + b) "z" + concat = foldr (a: b: a + b) "z" concat [ "a" "b" "c" ] => "abcz" + # different types + strange = foldr (int: str: toString (int + 1) + str) "a" + strange [ 1 2 3 4 ] + => "2345a" */ - fold = op: nul: list: + foldr = op: nul: list: let len = length list; fold' = n: @@ -35,13 +40,25 @@ rec { else op (elemAt list n) (fold' (n + 1)); in fold' 0; - /* Left fold: `fold op nul [x_1 x_2 ... x_n] == op (... (op (op nul - x_1) x_2) ... x_n)'. + /* `fold' is an alias of `foldr' for historic reasons */ + # FIXME(Profpatsch): deprecate? + fold = foldr; + + + /* “left fold”, like `foldr', but from the left: + `foldl op nul [x_1 x_2 ... x_n] == op (... (op (op nul x_1) x_2) ... x_n)`. + + Type: + foldl :: (b -> a -> b) -> b -> [a] -> b Example: lconcat = foldl (a: b: a + b) "z" lconcat [ "a" "b" "c" ] => "zabc" + # different types + lstrange = foldl (str: int: str + toString (int + 1)) "" + strange [ 1 2 3 4 ] + => "a2345" */ foldl = op: nul: list: let @@ -52,7 +69,7 @@ rec { else op (foldl' (n - 1)) (elemAt list n); in foldl' (length list - 1); - /* Strict version of foldl. + /* Strict version of `foldl'. The difference is that evaluation is forced upon access. Usually used with small whole results (in contract with lazily-generated list or large @@ -140,7 +157,7 @@ rec { any isString [ 1 { } ] => false */ - any = builtins.any or (pred: fold (x: y: if pred x then true else y) false); + any = builtins.any or (pred: foldr (x: y: if pred x then true else y) false); /* Return true iff function `pred' returns true for all elements of `list'. @@ -151,7 +168,7 @@ rec { all (x: x < 3) [ 1 2 3 ] => false */ - all = builtins.all or (pred: fold (x: y: if pred x then y else false) true); + all = builtins.all or (pred: foldr (x: y: if pred x then y else false) true); /* Count how many times function `pred' returns true for the elements of `list'. @@ -219,7 +236,7 @@ rec { => { right = [ 5 3 4 ]; wrong = [ 1 2 ]; } */ partition = builtins.partition or (pred: - fold (h: t: + foldr (h: t: if pred h then { right = [h] ++ t.right; wrong = t.wrong; } else { right = t.right; wrong = [h] ++ t.wrong; }