Sebastian Walz 860d31cee1
Tohu vaBohu
2023-04-21 00:22:52 +02:00

344 lines
8.3 KiB
Nix

{ intrinsics, list, type, ... }:
let
Dictionary
= type "Dictionary"
{
from#: { T... } -> { string -> T }
= dictionary:
Dictionary.instanciate
{
inherit dictionary;
__functor
= { dictionary, ... }:
key:
dictionary.${key} or null;
};
};
filter# (string -> T -> bool) -> { string -> T } -> { string -> T }
= predicate:
filterMap predicate (x: x);
filterKeys# (string -> bool) -> { string -> T } -> { string -> T }
= predicate:
filter (key: value: predicate key);
filterMap# (string -> T -> bool) -> (string -> T -> U) -> { string -> T } -> { string -> U }
= predicate:
mapping:
{ ... } @ dictionary:
list.fold
(
{ ... } @ dictionary':
{ key, value }:
if (predicate key value)
then
dictionary'
// {
${key} = mapping value;
}
else
dictionary'
)
{}
(getKeys dictionary);
filterValues# (T -> bool) -> { string -> T } -> { string -> T }
= predicate:
filter (key: predicate);
fold#: (S -> { key: string, value: T } -> S) -> S -> { string -> T } -> S
= function:
state:
dictionary:
list.fold function state (toList dictionary);
fromList#: [ { key: string, value: T } ] -> { string -> T }
= list.fold
(
{ ... } @ dictionary:
{ key, value }:
if dictionary.${key} or false != dictionary.${key} or true
then
dictionary
// {
${key} = value;
}
else
throw "Key »${key}« already in dictionary!"
)
{ };
get#:
= intrinsics.getAttr
or (
key:
dictionary:
dictionary.${key}
);
getOr#: string -> { string -> T } -> T -> T
= key:
dictionary:
default:
dictionary.${key} or default;
getKeys#: { string -> T } -> [ string ]
= intrinsics.attrNames;
# string -> { ... } -> bool
hasKey#:
= intrinsics.hasAttr
or (
name:
dictionary:
dictionary.${name} or true == dictionary.${name} or false
);
map#: (string -> T -> U) -> { string -> T } -> { string -> U }
= intrinsics.mapAttrs
or (
mapping:
{ ... } @ dictionary:
list.fold
(
{ ... } @ dictionary':
key:
dictionary'
// {
${key} = mapping key dictionary.${key};
}
)
{ }
( getKeys dictionary )
);
new = Dictionary {};
toList#: { string -> T } -> [ { key: string, value: T } ]
= dictionary:
list.fold
(
pairs:
key:
pairs
++ [
{
inherit key;
value = dictionary.${key};
}
]
)
[]
(getKeys dictionary);
in
Dictionary
// {
inherit Dictionary;
inherit filter map getKeys;
inherit fromList toList;
}
/*
# string -> [ { T... } ] -> [ T ]
# where T: Any
collect
= intrinsics.catAttrs
or (
name:
pairs:
list.fold
(
result:
{ ... } @ entry:
if hasAttribute name entry
then
result ++ [ entry.${name} ]
else
result
)
[ ]
pairs
);
# { T } -> [ string ] -> { T... }
# where T: Any:
filterByName
= { ... } @ dictionary:
keys:
fromList (list.map (name: { inherit name; value = dictionary.${name}; }) keys);
filterKeys# F -> { T } -> { T }
# where
# F: string -> bool,
# T: Any
= predicate:
{ ... } @ dictionary:
filterByName dictionary (list.filter predicate (names dictionary));
filterValue# F -> { T } -> { T }
# where
# F: T -> bool,
# T: Any
= predicate:
{ ... } @ dictionary:
filterByName dictionary (list.filter (name: predicate dictionary.${name}) (names dictionary));
# D -> [ T ] -> { D... }
# where
# F: T -> R,
# T, R: Any:
fromListDefault
= value:
list:
fromList (list.map (name: { inherit name value; }));
# F -> [ T ] -> { R... }
# where
# F: T -> { name: string, value: R },
# T, R: Any:
fromListMapped
= function:
list:
fromList (list.map function list);
# F -> [ T ] -> { R... }
# where
# F: int -> T -> { name: string, value: R },
# T, R: Any:
fromListIMapped
= function:
list:
fromList (list.imap function list);
# F -> [ T ] -> { R... }
# where
# F: T -> R,
# T, R: Any:
fromListMappedValue
= function:
list:
fromList (list.map (name: { inherit name; value = function name; }) list);
# F -> [ T ] -> { R... }
# where
# F: int -> T -> R,
# T, R: Any:
fromListIMappedValue
= function:
list:
fromList (list.imap (index: name: { inherit name; value = function index name; }) list);
# { ... } -> { ... } -> { ... }
intersect
= intrinsics.intersectAttrs
or (
left:
right:
list.fold
(
result:
entry:
if hasAttribute entry right
then
result // { ${entry} = right.${entry}; }
else
result
)
{ }
(names left)
);
mapNamesAndValues#: F -> { T... } -> { R... }
# where
# F: string -> T -> { name: string, value: R }
# T, R: Any,
= function:
dictionary:
fromList ( mapToList function dictionary );
# F -> { T... } -> { R... }
# where
# F: T -> R,
# T, R: Any:
mapValues
= function:
map
(
_:
value:
function value
);
# F -> { T... } -> [ R ]
# where
# F: string -> T -> R,
# T, R: Any:
mapToList
= function:
{ ... } @ dictionary:
values ( map function dictionary );
pair#: n, T @ n:[ string ] -> n:[ T ] -> { T }
= names:
values:
if isList names
&& isList values
&& length names == length values
then
fromListIMappedValue (index: name: list.get values index) names
else
debug'.panic "pair" "Names and Values must be two lists of same length!";
pairNameWithValue
= name: value: { inherit name value; };
# { ... } -> [ string ] -> { ... }:
remove
= intrinsics.removeAttrs
or (
{ ... } @ dictionary:
list:
list.fold
(
result:
name:
if !( find list name )
then
result
// {
${name} = dictionary.${name};
}
else
result
)
{ }
(names dictionary)
);
# { T... } -> string -> T
# where T: Any:
select = { ... } @ dictionary: field: dictionary.${field};
# { ... } -> [ T ]
# where T: Any
values
= intrinsics.attrValues
or (
{ ... } @ dictionary:
list.map (name: dictionary.${name}) (names dictionary)
);
in
{
inherit collect filter filterByName filterKeys filterValue fold fromList fromListDefault fromListMapped mapNamesAndValues
fromListMappedValue get getOr hasAttribute intersect map mapToList mapValues names pair pairNameWithValue
remove select values;
}
*/