restructure std -> nib.types + change type naming convention
This commit is contained in:
parent
b9f2acf7e7
commit
eac4161b36
11 changed files with 129 additions and 139 deletions
|
|
@ -1,118 +0,0 @@
|
|||
{lists, ...}: rec {
|
||||
nameValuePair = name: value: {inherit name value;};
|
||||
|
||||
identityAttrs = value: {${value} = value;};
|
||||
|
||||
identityAttrsList = values: builtins.map (v: identityAttrs v) values;
|
||||
|
||||
/**
|
||||
Generate an attribute set by mapping a function over a list of
|
||||
attribute names.
|
||||
|
||||
# Inputs
|
||||
|
||||
`names`
|
||||
|
||||
: Names of values in the resulting attribute set.
|
||||
|
||||
`f`
|
||||
|
||||
: A function, given the name of the attribute, returns the attribute's value.
|
||||
|
||||
# Type
|
||||
|
||||
```
|
||||
genAttrs :: [ String ] -> (String -> Any) -> AttrSet
|
||||
```
|
||||
|
||||
# Examples
|
||||
:::{.example}
|
||||
## `lib.attrsets.genAttrs` usage example
|
||||
|
||||
```nix
|
||||
genAttrs [ "foo" "bar" ] (name: "x_" + name)
|
||||
=> { foo = "x_foo"; bar = "x_bar"; }
|
||||
```
|
||||
|
||||
:::
|
||||
*/
|
||||
genAttrs = names: f: genAttrs' names (n: nameValuePair n (f n));
|
||||
|
||||
/**
|
||||
Like `genAttrs`, but allows the name of each attribute to be specified in addition to the value.
|
||||
The applied function should return both the new name and value as a `nameValuePair`.
|
||||
::: {.warning}
|
||||
In case of attribute name collision the first entry determines the value,
|
||||
all subsequent conflicting entries for the same name are silently ignored.
|
||||
:::
|
||||
|
||||
# Inputs
|
||||
|
||||
`xs`
|
||||
|
||||
: A list of strings `s` used as generator.
|
||||
|
||||
`f`
|
||||
|
||||
: A function, given a string `s` from the list `xs`, returns a new `nameValuePair`.
|
||||
|
||||
# Type
|
||||
|
||||
```
|
||||
genAttrs' :: [ Any ] -> (Any -> { name :: String; value :: Any; }) -> AttrSet
|
||||
```
|
||||
|
||||
# Examples
|
||||
:::{.example}
|
||||
## `lib.attrsets.genAttrs'` usage example
|
||||
|
||||
```nix
|
||||
genAttrs' [ "foo" "bar" ] (s: nameValuePair ("x_" + s) ("y_" + s))
|
||||
=> { x_foo = "y_foo"; x_bar = "y_bar"; }
|
||||
```
|
||||
|
||||
:::
|
||||
*/
|
||||
genAttrs' = xs: f: builtins.listToAttrs (map f xs);
|
||||
|
||||
mapAttrsRecursiveCond = cond: f: set: let
|
||||
recurse = path:
|
||||
builtins.mapAttrs (
|
||||
name: value:
|
||||
if builtins.isAttrs value && cond value
|
||||
then recurse (path ++ [name]) value
|
||||
else f (path ++ [name]) value
|
||||
);
|
||||
in
|
||||
recurse [] set;
|
||||
|
||||
mapAttrsRecursive = f: set: mapAttrsRecursiveCond (as: true) f set;
|
||||
|
||||
# form: attrValueAt :: xs -> path -> value
|
||||
# given path as a list of strings, return that value of an
|
||||
# attribute set at that path
|
||||
attrValueAt = lists.foldl (l: r:
|
||||
if l != null && builtins.hasAttr r l
|
||||
then l.${r}
|
||||
else null);
|
||||
|
||||
mergeAttrsList = list: let
|
||||
# `binaryMerge start end` merges the elements at indices `index` of `list` such that `start <= index < end`
|
||||
# Type: Int -> Int -> Attrs
|
||||
binaryMerge = start: end:
|
||||
# assert start < end; # Invariant
|
||||
if end - start >= 2
|
||||
then
|
||||
# If there's at least 2 elements, split the range in two, recurse on each part and merge the result
|
||||
# The invariant is satisfied because each half will have at least 1 element
|
||||
binaryMerge start (start + (end - start) / 2) // binaryMerge (start + (end - start) / 2) end
|
||||
else
|
||||
# Otherwise there will be exactly 1 element due to the invariant, in which case we just return it directly
|
||||
builtins.elemAt list start;
|
||||
in
|
||||
if list == []
|
||||
then
|
||||
# Calling binaryMerge as below would not satisfy its invariant
|
||||
{}
|
||||
else binaryMerge 0 (builtins.length list);
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
{...}: let
|
||||
attrs = import ./attrs.nix {inherit lists;};
|
||||
fault = import ./fault.nix {};
|
||||
lists = import ./lists.nix {};
|
||||
result = import ./result.nix {inherit lists;};
|
||||
in
|
||||
attrs.mergeAttrsList [
|
||||
# submodule is included directly to this module (ie self.myFunc)
|
||||
|
||||
# submodule content is accessible first by submodule name
|
||||
# then by the name of the content (ie self.submodule.myFunc)
|
||||
{inherit attrs fault lists result;}
|
||||
]
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{...}: rec {
|
||||
# Fault Monad
|
||||
# Wrapper around an error (ie builtins.abort)
|
||||
Fault = error: {
|
||||
error = error;
|
||||
};
|
||||
|
||||
# Pattern Matching
|
||||
isFault = F: builtins.attrNames F == ["error"];
|
||||
|
||||
# Unwrap (Monadic Return Operation)
|
||||
unwrap = F: F.error;
|
||||
|
||||
# Map (Monadic Bind Operation)
|
||||
map = f: F: Fault (f (unwrap F));
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
{...}: rec {
|
||||
foldl = op: nul: list: let
|
||||
foldl' = n:
|
||||
if n == -1
|
||||
then nul
|
||||
else op (foldl' (n - 1)) (builtins.elemAt list n);
|
||||
in
|
||||
foldl' (builtins.length list - 1);
|
||||
|
||||
crossLists = f: foldl (fs: args: builtins.concatMap (f: map f args) fs) [f];
|
||||
|
||||
findFirstIndex = pred: default: list: let
|
||||
# A naive recursive implementation would be much simpler, but
|
||||
# would also overflow the evaluator stack. We use `foldl'` as a workaround
|
||||
# because it reuses the same stack space, evaluating the function for one
|
||||
# element after another. We can't return early, so this means that we
|
||||
# sacrifice early cutoff, but that appears to be an acceptable cost. A
|
||||
# clever scheme with "exponential search" is possible, but appears over-
|
||||
# engineered for now. See https://github.com/NixOS/nixpkgs/pull/235267
|
||||
# Invariant:
|
||||
# - if index < 0 then el == elemAt list (- index - 1) and all elements before el didn't satisfy pred
|
||||
# - if index >= 0 then pred (elemAt list index) and all elements before (elemAt list index) didn't satisfy pred
|
||||
#
|
||||
# We start with index -1 and the 0'th element of the list, which satisfies the invariant
|
||||
resultIndex =
|
||||
builtins.foldl' (
|
||||
index: el:
|
||||
if index < 0
|
||||
then
|
||||
# No match yet before the current index, we need to check the element
|
||||
if pred el
|
||||
then
|
||||
# We have a match! Turn it into the actual index to prevent future iterations from modifying it
|
||||
-index - 1
|
||||
else
|
||||
# Still no match, update the index to the next element (we're counting down, so minus one)
|
||||
index - 1
|
||||
else
|
||||
# There's already a match, propagate the index without evaluating anything
|
||||
index
|
||||
) (-1)
|
||||
list;
|
||||
in
|
||||
if resultIndex < 0
|
||||
then default
|
||||
else resultIndex;
|
||||
|
||||
findFirst = pred: default: list: let
|
||||
index = findFirstIndex pred null list;
|
||||
in
|
||||
if index == null
|
||||
then default
|
||||
else builtins.elemAt list index;
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
{lists, ...}: rec {
|
||||
# Result Monad
|
||||
Ok = value: {
|
||||
success = true;
|
||||
value = value;
|
||||
};
|
||||
Err = err: {
|
||||
success = false;
|
||||
value = err;
|
||||
};
|
||||
|
||||
# Pattern Matching
|
||||
isResult = r: builtins.attrNames r == ["success" "value"];
|
||||
isOk = r: isResult r && r.success;
|
||||
isErr = r: isResult r && !r.success;
|
||||
|
||||
# Unwrap (Monadic Return Operation)
|
||||
unwrap = f: r:
|
||||
if isOk r
|
||||
then r.value
|
||||
else f r.value;
|
||||
|
||||
unwrapDefault = default: unwrap (_: default);
|
||||
|
||||
# Map (Monadic Bind Operation)
|
||||
identity = r: r;
|
||||
|
||||
map = r: f: g:
|
||||
if isOk r
|
||||
then Ok (f r.value)
|
||||
else Err (g r.value);
|
||||
mapOk = f: map f identity;
|
||||
mapErr = f: map identity f;
|
||||
|
||||
# Conditionals
|
||||
okOr = r: f:
|
||||
if isOk r
|
||||
then r
|
||||
else f r;
|
||||
|
||||
errOr = r: f:
|
||||
if isErr r
|
||||
then r
|
||||
else f r;
|
||||
|
||||
firstErr = lists.findFirst isErr (Ok "No errors");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue