Merge pull request #23929 from Profpatsch/lib-lists-doc
Improve lib/trivial and lib/lists docs
This commit is contained in:
commit
3bbab17575
@ -16,17 +16,22 @@ rec {
|
|||||||
*/
|
*/
|
||||||
singleton = x: [x];
|
singleton = x: [x];
|
||||||
|
|
||||||
/* "Fold" a binary function `op' between successive elements of
|
/* “right fold” a binary function `op' between successive elements of
|
||||||
`list' with `nul' as the starting value, i.e., `fold op nul [x_1
|
`list' with `nul' as the starting value, i.e.,
|
||||||
x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'. (This is
|
`foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'.
|
||||||
Haskell's foldr).
|
Type:
|
||||||
|
foldr :: (a -> b -> b) -> b -> [a] -> b
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
concat = fold (a: b: a + b) "z"
|
concat = foldr (a: b: a + b) "z"
|
||||||
concat [ "a" "b" "c" ]
|
concat [ "a" "b" "c" ]
|
||||||
=> "abcz"
|
=> "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
|
let
|
||||||
len = length list;
|
len = length list;
|
||||||
fold' = n:
|
fold' = n:
|
||||||
@ -35,13 +40,25 @@ rec {
|
|||||||
else op (elemAt list n) (fold' (n + 1));
|
else op (elemAt list n) (fold' (n + 1));
|
||||||
in fold' 0;
|
in fold' 0;
|
||||||
|
|
||||||
/* Left fold: `fold op nul [x_1 x_2 ... x_n] == op (... (op (op nul
|
/* `fold' is an alias of `foldr' for historic reasons */
|
||||||
x_1) x_2) ... x_n)'.
|
# 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:
|
Example:
|
||||||
lconcat = foldl (a: b: a + b) "z"
|
lconcat = foldl (a: b: a + b) "z"
|
||||||
lconcat [ "a" "b" "c" ]
|
lconcat [ "a" "b" "c" ]
|
||||||
=> "zabc"
|
=> "zabc"
|
||||||
|
# different types
|
||||||
|
lstrange = foldl (str: int: str + toString (int + 1)) ""
|
||||||
|
strange [ 1 2 3 4 ]
|
||||||
|
=> "a2345"
|
||||||
*/
|
*/
|
||||||
foldl = op: nul: list:
|
foldl = op: nul: list:
|
||||||
let
|
let
|
||||||
@ -52,7 +69,7 @@ rec {
|
|||||||
else op (foldl' (n - 1)) (elemAt list n);
|
else op (foldl' (n - 1)) (elemAt list n);
|
||||||
in foldl' (length list - 1);
|
in foldl' (length list - 1);
|
||||||
|
|
||||||
/* Strict version of foldl.
|
/* Strict version of `foldl'.
|
||||||
|
|
||||||
The difference is that evaluation is forced upon access. Usually used
|
The difference is that evaluation is forced upon access. Usually used
|
||||||
with small whole results (in contract with lazily-generated list or large
|
with small whole results (in contract with lazily-generated list or large
|
||||||
@ -140,7 +157,7 @@ rec {
|
|||||||
any isString [ 1 { } ]
|
any isString [ 1 { } ]
|
||||||
=> false
|
=> 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
|
/* Return true iff function `pred' returns true for all elements of
|
||||||
`list'.
|
`list'.
|
||||||
@ -151,7 +168,7 @@ rec {
|
|||||||
all (x: x < 3) [ 1 2 3 ]
|
all (x: x < 3) [ 1 2 3 ]
|
||||||
=> false
|
=> 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
|
/* Count how many times function `pred' returns true for the elements
|
||||||
of `list'.
|
of `list'.
|
||||||
@ -219,7 +236,7 @@ rec {
|
|||||||
=> { right = [ 5 3 4 ]; wrong = [ 1 2 ]; }
|
=> { right = [ 5 3 4 ]; wrong = [ 1 2 ]; }
|
||||||
*/
|
*/
|
||||||
partition = builtins.partition or (pred:
|
partition = builtins.partition or (pred:
|
||||||
fold (h: t:
|
foldr (h: t:
|
||||||
if pred h
|
if pred h
|
||||||
then { right = [h] ++ t.right; wrong = t.wrong; }
|
then { right = [h] ++ t.right; wrong = t.wrong; }
|
||||||
else { right = t.right; wrong = [h] ++ t.wrong; }
|
else { right = t.right; wrong = [h] ++ t.wrong; }
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
# to run these tests:
|
||||||
|
# nix-instantiate --eval --strict nixpkgs/lib/tests.nix
|
||||||
|
# if the resulting list is empty, all tests passed
|
||||||
let inherit (builtins) add; in
|
let inherit (builtins) add; in
|
||||||
with import ./default.nix;
|
with import ./default.nix;
|
||||||
|
|
||||||
@ -45,9 +48,33 @@ runTests {
|
|||||||
expected = ["b" "c"];
|
expected = ["b" "c"];
|
||||||
};
|
};
|
||||||
|
|
||||||
testFold = {
|
testFold =
|
||||||
expr = fold (builtins.add) 0 (range 0 100);
|
let
|
||||||
expected = 5050;
|
f = op: fold: fold op 0 (range 0 100);
|
||||||
|
# fold with associative operator
|
||||||
|
assoc = f builtins.add;
|
||||||
|
# fold with non-associative operator
|
||||||
|
nonAssoc = f builtins.sub;
|
||||||
|
in {
|
||||||
|
expr = {
|
||||||
|
assocRight = assoc foldr;
|
||||||
|
# right fold with assoc operator is same as left fold
|
||||||
|
assocRightIsLeft = assoc foldr == assoc foldl;
|
||||||
|
nonAssocRight = nonAssoc foldr;
|
||||||
|
nonAssocLeft = nonAssoc foldl;
|
||||||
|
# with non-assoc operator the fold results are not the same
|
||||||
|
nonAssocRightIsNotLeft = nonAssoc foldl != nonAssoc foldr;
|
||||||
|
# fold is an alias for foldr
|
||||||
|
foldIsRight = nonAssoc fold == nonAssoc foldr;
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
assocRight = 5050;
|
||||||
|
assocRightIsLeft = true;
|
||||||
|
nonAssocRight = 50;
|
||||||
|
nonAssocLeft = (-5050);
|
||||||
|
nonAssocRightIsNotLeft = true;
|
||||||
|
foldIsRight = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
testTake = testAllTrue [
|
testTake = testAllTrue [
|
||||||
|
@ -1,17 +1,44 @@
|
|||||||
rec {
|
rec {
|
||||||
|
|
||||||
# Identity function.
|
/* The identity function
|
||||||
|
For when you need a function that does “nothing”.
|
||||||
|
|
||||||
|
Type: id :: a -> a
|
||||||
|
*/
|
||||||
id = x: x;
|
id = x: x;
|
||||||
|
|
||||||
# Constant function.
|
/* The constant function
|
||||||
|
Ignores the second argument.
|
||||||
|
Or: Construct a function that always returns a static value.
|
||||||
|
|
||||||
|
Type: const :: a -> b -> a
|
||||||
|
Example:
|
||||||
|
let f = const 5; in f 10
|
||||||
|
=> 5
|
||||||
|
*/
|
||||||
const = x: y: x;
|
const = x: y: x;
|
||||||
|
|
||||||
# Named versions corresponding to some builtin operators.
|
|
||||||
|
## Named versions corresponding to some builtin operators.
|
||||||
|
|
||||||
|
/* Concat two strings */
|
||||||
concat = x: y: x ++ y;
|
concat = x: y: x ++ y;
|
||||||
|
|
||||||
|
/* boolean “or” */
|
||||||
or = x: y: x || y;
|
or = x: y: x || y;
|
||||||
|
|
||||||
|
/* boolean “and” */
|
||||||
and = x: y: x && y;
|
and = x: y: x && y;
|
||||||
|
|
||||||
|
/* Merge two attribute sets shallowly, right side trumps left
|
||||||
|
|
||||||
|
Example:
|
||||||
|
mergeAttrs { a = 1; b = 2; } // { b = 3; c = 4; }
|
||||||
|
=> { a = 1; b = 3; c = 4; }
|
||||||
|
*/
|
||||||
mergeAttrs = x: y: x // y;
|
mergeAttrs = x: y: x // y;
|
||||||
|
|
||||||
|
|
||||||
# Compute the fixed point of the given function `f`, which is usually an
|
# Compute the fixed point of the given function `f`, which is usually an
|
||||||
# attribute set that expects its final, non-recursive representation as an
|
# attribute set that expects its final, non-recursive representation as an
|
||||||
# argument:
|
# argument:
|
||||||
|
Loading…
Reference in New Issue
Block a user