labs/lib/src/default.nix

78 lines
2 KiB
Nix
Raw Normal View History

2024-06-01 11:00:53 +00:00
let
files = [
./attrs
./bools
./errors
./fp
./generators
./importers
2024-06-05 02:04:40 +00:00
./licenses
2024-06-01 11:00:53 +00:00
./lists
./math
./modules
./numbers
./options
./packages
./paths
./points
./strings
./types
./versions
];
libs = builtins.map (f: import f) files;
## Calculate the fixed point of a function. This will evaluate the function `f`
## until its result settles (or Nix's recursion limit is reached). This allows
## us to define recursive functions without worrying about the order of their
## definitions.
##
## @type (a -> a) -> a
fix = f: let
x = f x;
in
x;
## Merge two attribute sets recursively until a given predicate returns true.
## Any values that are _not_ attribute sets will be overridden with the value
## from `y` first if it exists and then `x` otherwise.
##
## @type Attrs a b c => (String -> Any -> Any -> Bool) -> a -> b -> c
mergeAttrsRecursiveUntil = predicate: x: y: let
process = path:
builtins.zipAttrsWith (
2024-06-03 09:57:13 +00:00
name: values: let
currentPath = path ++ [name];
2024-06-01 11:00:53 +00:00
isSingleValue = builtins.length values == 1;
isComplete =
predicate currentPath
(builtins.elemAt values 1)
(builtins.elemAt values 0);
in
if isSingleValue || isComplete
then builtins.elemAt values 0
else process currentPath values
);
in
process [] [x y];
## Merge two attribute sets recursively. Any values that are _not_ attribute sets
## will be overridden with the value from `y` first if it exists and then `x`
## otherwise.
##
## @type Attrs a b c => a -> b -> c
mergeAttrsRecursive =
mergeAttrsRecursiveUntil
(path: x: y:
!(builtins.isAttrs x && builtins.isAttrs y));
lib = fix (
self: let
merge = acc: create:
mergeAttrsRecursive acc (create self);
in
builtins.foldl' merge {} libs
);
in
lib.points.withExtend (lib.fp.const lib)