diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..751553b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.bak diff --git a/flake.nix b/flake.nix index fce19ff..db0ba25 100644 --- a/flake.nix +++ b/flake.nix @@ -1,10 +1,11 @@ { - description = "MyNib - My Nix Library"; + description = "NixTypes (nt)"; - inputs.systems.url = "github:nix-systems/default"; + inputs = { + systems.url = "github:nix-systems/default"; + mix.url = "github:emilelcb/mix"; + }; - outputs = {self, ...} @ inputs: let - systems = import inputs.systems; - in - import ./nib {inherit systems;}; + outputs = {...} @ inputs: + import ./nt inputs; } diff --git a/nib/default.nix b/nib/default.nix deleted file mode 100644 index faf755f..0000000 --- a/nib/default.nix +++ /dev/null @@ -1,27 +0,0 @@ -{systems, ...}: let - # TODO: move this to a new module - mkMod' = args: mod: import mod args; - mkMod = mkMod' {inherit systems nib;}; - - std = mkMod ./std; - panic = mkMod ./panic.nix; - parse = mkMod ./parse; - # patterns = mkMod ./patterns.nix; - - types = mkMod ./types; - typesystem = mkMod ./typesystem.nix; - - sys = mkMod ./sys.nix; - - nib = std.mergeAttrsList [ - # submodule content is accessible first by submodule name - # then by the name of the content (ie self.submodule.myFunc) - {inherit std types panic parse;} - - # submodule content accessible directly (ie self.myFunc) - # patterns - typesystem - sys - ]; -in - nib diff --git a/nib/enforce.nix b/nib/enforce.nix deleted file mode 100644 index d6801aa..0000000 --- a/nib/enforce.nix +++ /dev/null @@ -1,14 +0,0 @@ -{nib, ...}: rec { - enfType = type: T: - assert (nib.isType type T - || nib.panic.badType (nib.typeName type)); true; - - enfSameType = T1: T2: enfType (nib.typeOf T1) T2; - - enfAttrs = enfType (nib.typeOf {}); - enfList = enfType (nib.typeOf []); - enfListOf = type: L: - assert (enfList L - && builtins.all (T: nib.isType type T) L - || nib.panic.badType "List ${nib.typeName type}" L); true; -} diff --git a/nib/mod.nix b/nib/mod.nix deleted file mode 100644 index ea8f50d..0000000 --- a/nib/mod.nix +++ /dev/null @@ -1,2 +0,0 @@ -{...}: { -} diff --git a/nib/panic.nix b/nib/panic.nix deleted file mode 100644 index 5fb63b0..0000000 --- a/nib/panic.nix +++ /dev/null @@ -1,4 +0,0 @@ -{nib, ...}: { - badType = expect: x: - throw "Expected type ${expect} but got ${nib.typeOf x}."; -} diff --git a/nib/parse/default.nix b/nib/parse/default.nix deleted file mode 100644 index af28ce3..0000000 --- a/nib/parse/default.nix +++ /dev/null @@ -1,7 +0,0 @@ -{nib, ...} @ args: let - struct = import ./struct.nix args; -in - nib.std.mergeAttrsList [ - # submodule is included directly to this module (ie self.myFunc) - struct - ] diff --git a/nib/parse/struct.nix b/nib/parse/struct.nix deleted file mode 100644 index f806039..0000000 --- a/nib/parse/struct.nix +++ /dev/null @@ -1,111 +0,0 @@ -{nib, ...}: let - inherit - (nib.types) - Err - Ok' - firstErr - unwrapSome - isTerminal - unwrapTerminal - ; - - inherit - (nib.std) - attrValueAt - ; -in rec { - cmpStructErr' = errBadKeys: errBadValues: path: S: T: - if builtins.isAttrs S && builtins.isAttrs T - then let - keysS = builtins.attrNames S; - keysT = builtins.attrNames T; - in - # ensure all key names match, then recurse - if !(keysS == keysT) - then errBadKeys path keysS keysT - else - (firstErr - (map - (k: cmpStructErr' errBadKeys errBadValues (path ++ [k]) (keysS.${k}) (keysT.${k})) - keysS)) - else - # terminating leaf in recursion tree reached - # ensure values' types match - (builtins.typeOf S == builtins.typeOf T) - || errBadValues path S T; - - cmpStructErr = errBadKeys: errBadValues: cmpStructErr' errBadKeys errBadValues []; - - cmpStruct = - cmpStructErr - (path: _: _: - Err { - reason = "keys"; - inherit path; - }) - (_: _: _: Ok'); - - cmpTypedStruct = - cmpStructErr - (path: _: _: - Err { - reason = "keys"; - inherit path; - }) - (path: _: _: - Err { - reason = "values"; - inherit path; - }); - - cmpTypedPartialStruct = - cmpStructErr - (_: _: _: Ok') - (path: _: _: - Err { - reason = "values"; - inherit path; - }); - - # Alternative to mapAttrsRecursiveCond - # Allows mapping directly from a child path - recmapCondFrom = path: cond: f: T: let - delegate = path': recmapCondFrom path' cond f; - in - if builtins.isAttrs T && cond path T - then builtins.mapAttrs (attr: leaf: delegate (path ++ [attr]) leaf) T - # else if builtins.isList T - # then map (leaf: delegate leaf) - else f path T; - - recmapCond = recmapCondFrom []; - - # Alternative to mapAttrsRecursive - # NOTE: refuses to go beyond Terminal types - recmap = recmapCond (_: leaf: !(isTerminal leaf)); - - overrideStructCond = cond: f: S: ext: - recmapCond - cond - (path: leaf: - attrValueAt path ext - |> unwrapSome (_: f leaf)) - S; - - # overrideStruct ensures no properties are evaluated (entirely lazy) - # TODO: should this be called "overlayStructs" or something? (its not exactly a override...) - # NOTE: respects Terminal types - overrideStruct = - overrideStructCond - (_: leaf: !(isTerminal leaf)) - (leaf: - if isTerminal leaf - then unwrapTerminal leaf - else leaf); - - # # overrideTypedPartialStruct must evaluate properties (not lazy) - # # for lazy evaluation use overrideStruct instead! - # overrideTypedPartialStruct = overrideStructs' cmpTypedPartialStruct; - - overrideAttrs = A: B: A // B; -} diff --git a/nib/patterns.nix b/nib/patterns.nix deleted file mode 100644 index b78e927..0000000 --- a/nib/patterns.nix +++ /dev/null @@ -1,47 +0,0 @@ -{nib, ...}: let - # Rust inspired pattern matching syntax: - # resultA = match [platform arch] [ - # (Pattern ["darwin" Any] darwin_package) - # (Pattern ["openbsd" "x86_64"] openbsd_x86_64_package) - # (Pattern [(x: x == "linux") (y: y == "x86_64")] linux_x86_64_package) - # (Pattern (x: y: x == "linux" && y == "aarch64") linux_aarch64_package) - # (Pattern Any default_package) - # ]; - # resultB = match [platform arch] [ - # (["darwin" Any] |> case darwin_package) - # (["openbsd" "x86_64"] |> case openbsd_x86_64_package) - # ([(x: x == "linux") (y: y == "x86_64")] |> case linux_x86_64_package) - # ((x: y: x == "linux" && y == "aarch64") |> case linux_aarch64_package) - # (Any |> case default_package) - # ]; - types = nib.types; -in rec { - Pattern = pattern: return: throw "not implemented"; - case = return: pattern: Pattern pattern return; - - matchesPattern' = pattern: subject: let - recurse = p: s: - nib.isSameType p s - && ( - if nib.isList p - then builtins.all (map (p: recurse p)) (nib.std.zipLists) - else if nib.isAttrs p - then builtins.all () - else nib.eq p s - ); - in - recurse pattern subject; - - # maybe' :: TList a b -> TList [TPattern c d] -> TMaybe d - match' = subject: patterns: - nib.enfType (types.TList types.TPattern) patterns - && builtins.foldl' ( - fix: p: - if types.isNone fix - # maintain None as a fixed value - then fix - else matchesPattern' p - ) - types.Some - patterns; -} diff --git a/nib/std/attrs.nix b/nib/std/attrs.nix deleted file mode 100644 index 43cc2d1..0000000 --- a/nib/std/attrs.nix +++ /dev/null @@ -1,198 +0,0 @@ -{nib, ...}: let - inherit - (builtins) - all - attrNames - elemAt - filter - getAttr - hasAttr - isAttrs - length - listToAttrs - mapAttrs - ; - - inherit - (nib.std) - foldl - ; - - inherit - (nib.types) - nullableToMaybe - ; -in rec { - nameValuePair = name: value: {inherit name value;}; - - identityAttrs = value: {${value} = value;}; - - identityAttrsMany = values: map (v: identityAttrs v) values; - - hasAttrs = list: xs: all (x: hasAttr x xs) list; - - getAttrOr = default: name: xs: - if hasAttr name xs - then getAttr name xs - else default; - - /** - 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: listToAttrs (map f xs); - - /** - 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)); - - mapAttrsRecursiveCond = cond: f: set: let - recurse = path: - mapAttrs ( - name: value: let - next = path ++ [name]; - in - if isAttrs value && cond value - then recurse next value - else f next value - ); - in - recurse [] set; - - mapAttrsRecursive = f: set: mapAttrsRecursiveCond (as: true) f set; - - # form: attrValueAt :: list string -> set -> Maybe Any - # given path as a list of strings, return that value of an - # attribute set at that path - attrValueAt = path: xs: - foldl (left: right: - if isAttrs left && hasAttr right left - then left.${right} - else null) - xs - path - |> nullableToMaybe; - - 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 - elemAt list start; - in - if list == [] - then - # Calling binaryMerge as below would not satisfy its invariant - {} - else binaryMerge 0 (length list); - - /** - Filter an attribute set by removing all attributes for which the - given predicate return false. - - # Inputs - - `pred` - - : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute. - - - If possible, decide on `name` first and on `value` only if necessary. - This avoids evaluating the value if the name is already enough, making it possible, potentially, to have the argument reference the return value. - (Depending on context, that could still be considered a self reference by users; a common pattern in Nix.) - - - `filterAttrs` is occasionally the cause of infinite recursion in configuration systems that allow self-references. - To support the widest range of user-provided logic, perform the `filterAttrs` call as late as possible. - Typically that's right before using it in a derivation, as opposed to an implicit conversion whose result is accessible to the user's expressions. - - `set` - - : The attribute set to filter - - # Type - - ``` - filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet - ``` - - # Examples - :::{.example} - ## `lib.attrsets.filterAttrs` usage example - - ```nix - filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; } - => { foo = 1; } - ``` - - ::: - */ - filterAttrs = pred: set: removeAttrs set (filter (name: !pred name set.${name}) (attrNames set)); -} diff --git a/nib/std/default.nix b/nib/std/default.nix deleted file mode 100644 index 354b7ef..0000000 --- a/nib/std/default.nix +++ /dev/null @@ -1,14 +0,0 @@ -{...} @ args: let - attrs = import ./attrs.nix args; - functions = import ./functions.nix args; - lists = import ./lists.nix args; - strings = import ./strings.nix args; - trivial = import ./trivial.nix args; -in - attrs.mergeAttrsList [ - attrs - functions - lists - strings - trivial - ] diff --git a/nib/std/functions.nix b/nib/std/functions.nix deleted file mode 100644 index 00179d6..0000000 --- a/nib/std/functions.nix +++ /dev/null @@ -1,9 +0,0 @@ -{nib, ...}: let - inherit - (nib.std) - min - ; -in { - # yeah fuck the waiter!! it was cold anyways :( - flipCurry = f: a: b: f b a; -} diff --git a/nib/std/lists.nix b/nib/std/lists.nix deleted file mode 100644 index 4597158..0000000 --- a/nib/std/lists.nix +++ /dev/null @@ -1,85 +0,0 @@ -{nib, ...}: let - inherit - (builtins) - concatMap - elemAt - foldl' - genList - length - ; - inherit - (nib.std) - min - ; -in rec { - foldl = op: nul: list: let - foldl' = n: - if n == -1 - then nul - else op (foldl' (n - 1)) (elemAt list n); - in - foldl' (length list - 1); - - crossLists = f: foldl (fs: args: 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 = - 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 elemAt list index; - - zipListsWith = f: fst: snd: - genList (n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd)); - - # zipLists = zipListsWith (fst: snd: {inherit fst snd;}); - - sublist = start: count: list: let - len = length list; - in - genList (n: elemAt list (n + start)) ( - if start >= len - then 0 - else if start + count > len - then len - start - else count - ); - - take = sublist 0; -} diff --git a/nib/std/strings.nix b/nib/std/strings.nix deleted file mode 100644 index 6a30cff..0000000 --- a/nib/std/strings.nix +++ /dev/null @@ -1,58 +0,0 @@ -{nib, ...}: let - inherit - (builtins) - isPath - genList - replaceStrings - substring - stringLength - ; - - inherit - (nib.std) - warnIf - ; -in rec { - # re-export builtin string methods - inherit - replaceStrings - substring - stringLength - ; - - escape = list: replaceStrings list (map (c: "\\${c}") list); - - escapeRegex = escape (stringToCharacters "\\[{()^$?*+|."); - - hasInfix = infix: content: - # Before 23.05, paths would be copied to the store before converting them - # to strings and comparing. This was surprising and confusing. - warnIf (isPath infix) - '' - lib.strings.hasInfix: The first argument (${toString infix}) is a path value, but only strings are supported. - There is almost certainly a bug in the calling code, since this function always returns `false` in such a case. - This function also copies the path to the Nix store, which may not be what you want. - This behavior is deprecated and will throw an error in the future.'' - (builtins.match ".*${escapeRegex infix}.*" "${content}" != null); - - removeSuffix = suffix: str: - # Before 23.05, paths would be copied to the store before converting them - # to strings and comparing. This was surprising and confusing. - warnIf (isPath suffix) - '' - lib.strings.removeSuffix: The first argument (${toString suffix}) is a path value, but only strings are supported. - There is almost certainly a bug in the calling code, since this function never removes any suffix in such a case. - This function also copies the path to the Nix store, which may not be what you want. - This behavior is deprecated and will throw an error in the future.'' - ( - let - sufLen = stringLength suffix; - sLen = stringLength str; - in - if sufLen <= sLen && suffix == substring (sLen - sufLen) sufLen str - then substring 0 (sLen - sufLen) str - else str - ); - - stringToCharacters = s: genList (p: substring p 1 s) (stringLength s); -} diff --git a/nib/std/trivial.nix b/nib/std/trivial.nix deleted file mode 100644 index cb50a53..0000000 --- a/nib/std/trivial.nix +++ /dev/null @@ -1,23 +0,0 @@ -{...}: let - inherit - (builtins) - warn - ; -in { - id = x: x; - - min = x: y: - if x < y - then x - else y; - - max = x: y: - if x > y - then x - else y; - - warnIf = cond: msg: - if cond - then warn msg - else x: x; -} diff --git a/nib/std/trivial.nix.bak b/nib/std/trivial.nix.bak deleted file mode 100644 index 2f62817..0000000 --- a/nib/std/trivial.nix.bak +++ /dev/null @@ -1,1251 +0,0 @@ -{lib}: { - ## Simple (higher order) functions - - /** - The identity function - For when you need a function that does “nothing”. - - # Inputs - - `x` - - : The value to return - - # Type - - ``` - id :: a -> a - ``` - */ - id = x: x; - - /** - The constant function - - Ignores the second argument. If called with only one argument, - constructs a function that always returns a static value. - - # Inputs - - `x` - - : Value to return - - `y` - - : Value to ignore - - # Type - - ``` - const :: a -> b -> a - ``` - - # Examples - :::{.example} - ## `lib.trivial.const` usage example - - ```nix - let f = const 5; in f 10 - => 5 - ``` - - ::: - */ - const = x: y: x; - - /** - Pipes a value through a list of functions, left to right. - - # Inputs - - `value` - - : Value to start piping. - - `fns` - - : List of functions to apply sequentially. - - # Type - - ``` - pipe :: a -> [] -> - ``` - - # Examples - :::{.example} - ## `lib.trivial.pipe` usage example - - ```nix - pipe 2 [ - (x: x + 2) # 2 + 2 = 4 - (x: x * 2) # 4 * 2 = 8 - ] - => 8 - - # ideal to do text transformations - pipe [ "a/b" "a/c" ] [ - - # create the cp command - (map (file: ''cp "${src}/${file}" $out\n'')) - - # concatenate all commands into one string - lib.concatStrings - - # make that string into a nix derivation - (pkgs.runCommand "copy-to-out" {}) - - ] - => - - The output type of each function has to be the input type - of the next function, and the last function returns the - final value. - ``` - - ::: - */ - pipe = builtins.foldl' (x: f: f x); - - # note please don’t add a function like `compose = flip pipe`. - # This would confuse users, because the order of the functions - # in the list is not clear. With pipe, it’s obvious that it - # goes first-to-last. With `compose`, not so much. - - ## Named versions corresponding to some builtin operators. - - /** - Concatenate two lists - - # Inputs - - `x` - - : 1\. Function argument - - `y` - - : 2\. Function argument - - # Type - - ``` - concat :: [a] -> [a] -> [a] - ``` - - # Examples - :::{.example} - ## `lib.trivial.concat` usage example - - ```nix - concat [ 1 2 ] [ 3 4 ] - => [ 1 2 3 4 ] - ``` - - ::: - */ - concat = x: y: x ++ y; - - /** - boolean “or” - - # Inputs - - `x` - - : 1\. Function argument - - `y` - - : 2\. Function argument - */ - or = x: y: x || y; - - /** - boolean “and” - - # Inputs - - `x` - - : 1\. Function argument - - `y` - - : 2\. Function argument - */ - and = x: y: x && y; - - /** - boolean “exclusive or” - - # Inputs - - `x` - - : 1\. Function argument - - `y` - - : 2\. Function argument - */ - # We explicitly invert the arguments purely as a type assertion. - # This is invariant under XOR, so it does not affect the result. - xor = x: y: (!x) != (!y); - - /** - bitwise “not” - */ - bitNot = builtins.sub (-1); - - /** - Convert a boolean to a string. - - This function uses the strings "true" and "false" to represent - boolean values. Calling `toString` on a bool instead returns "1" - and "" (sic!). - - # Inputs - - `b` - - : 1\. Function argument - - # Type - - ``` - boolToString :: bool -> string - ``` - */ - boolToString = b: - if b - then "true" - else "false"; - - /** - Converts a boolean to a string. - - This function uses the strings "yes" and "no" to represent - boolean values. - - # Inputs - - `b` - - : The boolean to convert - - # Type - - ``` - boolToYesNo :: bool -> string - ``` - */ - boolToYesNo = b: - if b - then "yes" - else "no"; - - /** - Merge two attribute sets shallowly, right side trumps left - - # Type - - ``` - mergeAttrs :: attrs -> attrs -> attrs - ``` - - # Inputs - - `x` - - : Left attribute set - - `y` - - : Right attribute set (higher precedence for equal keys) - - # Examples - :::{.example} - ## `lib.trivial.mergeAttrs` usage example - - ```nix - mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; } - => { a = 1; b = 3; c = 4; } - ``` - - ::: - */ - mergeAttrs = x: y: x // y; - - /** - Flip the order of the arguments of a binary function. - - # Inputs - - `f` - - : 1\. Function argument - - `a` - - : 2\. Function argument - - `b` - - : 3\. Function argument - - # Type - - ``` - flip :: (a -> b -> c) -> (b -> a -> c) - ``` - - # Examples - :::{.example} - ## `lib.trivial.flip` usage example - - ```nix - flip concat [1] [2] - => [ 2 1 ] - ``` - - ::: - */ - flip = f: a: b: - f b a; - - /** - Returns `maybeValue` if not null, otherwise return `default`. - - # Inputs - - `default` - - : 1\. Function argument - - `maybeValue` - - : 2\. Function argument - - # Examples - :::{.example} - ## `lib.trivial.defaultTo` usage example - - ```nix - defaultTo "default" null - => "default" - defaultTo "default" "foo" - => "foo" - defaultTo "default" false - => false - ``` - - ::: - */ - defaultTo = default: maybeValue: - if maybeValue != null - then maybeValue - else default; - - /** - Apply function if the supplied argument is non-null. - - # Inputs - - `f` - - : Function to call - - `a` - - : Argument to check for null before passing it to `f` - - # Examples - :::{.example} - ## `lib.trivial.mapNullable` usage example - - ```nix - mapNullable (x: x+1) null - => null - mapNullable (x: x+1) 22 - => 23 - ``` - - ::: - */ - mapNullable = f: a: - if a == null - then a - else f a; - - # Pull in some builtins not included elsewhere. - inherit - (builtins) - pathExists - readFile - isBool - isInt - isFloat - add - sub - lessThan - seq - deepSeq - genericClosure - bitAnd - bitOr - bitXor - ; - - ## nixpkgs version strings - - /** - Returns the current full nixpkgs version number. - */ - version = release + versionSuffix; - - /** - Returns the current nixpkgs release number as string. - */ - release = lib.strings.fileContents ./.version; - - /** - The latest release that is supported, at the time of release branch-off, - if applicable. - - Ideally, out-of-tree modules should be able to evaluate cleanly with all - supported Nixpkgs versions (master, release and old release until EOL). - So if possible, deprecation warnings should take effect only when all - out-of-tree expressions/libs/modules can upgrade to the new way without - losing support for supported Nixpkgs versions. - - This release number allows deprecation warnings to be implemented such that - they take effect as soon as the oldest release reaches end of life. - */ - oldestSupportedRelease = - # Update on master only. Do not backport. - 2505; - - /** - Whether a feature is supported in all supported releases (at the time of - release branch-off, if applicable). See `oldestSupportedRelease`. - - # Inputs - - `release` - - : Release number of feature introduction as an integer, e.g. 2111 for 21.11. - Set it to the upcoming release, matching the nixpkgs/.version file. - */ - isInOldestRelease = - lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2411) - "lib.isInOldestRelease is deprecated. Use lib.oldestSupportedReleaseIsAtLeast instead." - lib.oldestSupportedReleaseIsAtLeast; - - /** - Alias for `isInOldestRelease` introduced in 24.11. - Use `isInOldestRelease` in expressions outside of Nixpkgs for greater compatibility. - */ - oldestSupportedReleaseIsAtLeast = release: release <= lib.trivial.oldestSupportedRelease; - - /** - Returns the current nixpkgs release code name. - - On each release the first letter is bumped and a new animal is chosen - starting with that new letter. - */ - codeName = "Yarara"; - - /** - Returns the current nixpkgs version suffix as string. - */ - versionSuffix = let - suffixFile = ../.version-suffix; - in - if pathExists suffixFile - then lib.strings.fileContents suffixFile - else "pre-git"; - - /** - Attempts to return the the current revision of nixpkgs and - returns the supplied default value otherwise. - - # Inputs - - `default` - - : Default value to return if revision can not be determined - - # Type - - ``` - revisionWithDefault :: string -> string - ``` - */ - revisionWithDefault = default: let - revisionFile = "${toString ./..}/.git-revision"; - gitRepo = "${toString ./..}/.git"; - in - if lib.pathIsGitRepo gitRepo - then lib.commitIdFromGitRepo gitRepo - else if lib.pathExists revisionFile - then lib.fileContents revisionFile - else default; - - nixpkgsVersion = warn "lib.nixpkgsVersion is a deprecated alias of lib.version." version; - - /** - Determine whether the function is being called from inside a Nix - shell. - - # Type - - ``` - inNixShell :: bool - ``` - */ - inNixShell = builtins.getEnv "IN_NIX_SHELL" != ""; - - /** - Determine whether the function is being called from inside pure-eval mode - by seeing whether `builtins` contains `currentSystem`. If not, we must be in - pure-eval mode. - - # Type - - ``` - inPureEvalMode :: bool - ``` - */ - inPureEvalMode = !builtins ? currentSystem; - - ## Integer operations - - /** - Returns minimum of two numbers. - - # Inputs - - `x` - - : 1\. Function argument - - `y` - - : 2\. Function argument - */ - min = x: y: - if x < y - then x - else y; - - /** - Returns maximum of two numbers. - - # Inputs - - `x` - - : 1\. Function argument - - `y` - - : 2\. Function argument - */ - max = x: y: - if x > y - then x - else y; - - /** - Integer modulus - - # Inputs - - `base` - - : 1\. Function argument - - `int` - - : 2\. Function argument - - # Examples - :::{.example} - ## `lib.trivial.mod` usage example - - ```nix - mod 11 10 - => 1 - mod 1 10 - => 1 - ``` - - ::: - */ - mod = base: int: base - (int * (builtins.div base int)); - - ## Comparisons - - /** - C-style comparisons - - a < b, compare a b => -1 - a == b, compare a b => 0 - a > b, compare a b => 1 - - # Inputs - - `a` - - : 1\. Function argument - - `b` - - : 2\. Function argument - */ - compare = a: b: - if a < b - then -1 - else if a > b - then 1 - else 0; - - /** - Split type into two subtypes by predicate `p`, take all elements - of the first subtype to be less than all the elements of the - second subtype, compare elements of a single subtype with `yes` - and `no` respectively. - - # Inputs - - `p` - - : Predicate - - `yes` - - : Comparison function if predicate holds for both values - - `no` - - : Comparison function if predicate holds for neither value - - `a` - - : First value to compare - - `b` - - : Second value to compare - - # Type - - ``` - (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int) - ``` - - # Examples - :::{.example} - ## `lib.trivial.splitByAndCompare` usage example - - ```nix - let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in - - cmp "a" "z" => -1 - cmp "fooa" "fooz" => -1 - - cmp "f" "a" => 1 - cmp "fooa" "a" => -1 - # while - compare "fooa" "a" => 1 - ``` - - ::: - */ - splitByAndCompare = p: yes: no: a: b: - if p a - then - if p b - then yes a b - else -1 - else if p b - then 1 - else no a b; - - /** - Reads a JSON file. - - # Examples - :::{.example} - ## `lib.trivial.importJSON` usage example - - example.json - ```json - { - "title": "Example JSON", - "hello": { - "world": "foo", - "bar": { - "foobar": true - } - } - } - ``` - - ```nix - importJSON ./example.json - => { - title = "Example JSON"; - hello = { - world = "foo"; - bar = { - foobar = true; - }; - }; - } - ``` - - ::: - - # Inputs - - `path` - - : 1\. Function argument - - # Type - - ``` - importJSON :: path -> any - ``` - */ - importJSON = path: builtins.fromJSON (builtins.readFile path); - - /** - Reads a TOML file. - - # Examples - :::{.example} - ## `lib.trivial.importTOML` usage example - - example.toml - ```toml - title = "TOML Example" - - [hello] - world = "foo" - - [hello.bar] - foobar = true - ``` - - ```nix - importTOML ./example.toml - => { - title = "TOML Example"; - hello = { - world = "foo"; - bar = { - foobar = true; - }; - }; - } - ``` - - ::: - - # Inputs - - `path` - - : 1\. Function argument - - # Type - - ``` - importTOML :: path -> any - ``` - */ - importTOML = path: fromTOML (builtins.readFile path); - - /** - `warn` *`message`* *`value`* - - Print a warning before returning the second argument. - - See [`builtins.warn`](https://nix.dev/manual/nix/latest/language/builtins.html#builtins-warn) (Nix >= 2.23). - On older versions, the Nix 2.23 behavior is emulated with [`builtins.trace`](https://nix.dev/manual/nix/latest/language/builtins.html#builtins-warn), including the [`NIX_ABORT_ON_WARN`](https://nix.dev/manual/nix/latest/command-ref/conf-file#conf-abort-on-warn) behavior, but not the `nix.conf` setting or command line option. - - # Inputs - - *`message`* (String) - - : Warning message to print before evaluating *`value`*. - - *`value`* (any value) - - : Value to return as-is. - - # Type - - ``` - String -> a -> a - ``` - */ - warn = - # Since Nix 2.23, https://github.com/NixOS/nix/pull/10592 - builtins.warn or ( - let - mustAbort = lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") [ - "1" - "true" - "yes" - ]; - in - # Do not eta reduce v, so that we have the same strictness as `builtins.warn`. - msg: v: - # `builtins.warn` requires a string message, so we enforce that in our implementation, so that callers aren't accidentally incompatible with newer Nix versions. - assert isString msg; - if mustAbort - then - builtins.trace "[1;31mevaluation warning:[0m ${msg}" ( - abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors." - ) - else builtins.trace "[1;35mevaluation warning:[0m ${msg}" v - ); - - /** - `warnIf` *`condition`* *`message`* *`value`* - - Like `warn`, but only warn when the first argument is `true`. - - # Inputs - - *`condition`* (Boolean) - - : `true` to trigger the warning before continuing with *`value`*. - - *`message`* (String) - - : Warning message to print before evaluating - - *`value`* (any value) - - : Value to return as-is. - - # Type - - ``` - Bool -> String -> a -> a - ``` - */ - warnIf = cond: msg: - if cond - then warn msg - else x: x; - - /** - `warnIfNot` *`condition`* *`message`* *`value`* - - Like `warnIf`, but negated: warn if the first argument is `false`. - - # Inputs - - *`condition`* - - : `false` to trigger the warning before continuing with `val`. - - *`message`* - - : Warning message to print before evaluating *`value`*. - - *`value`* - - : Value to return as-is. - - # Type - - ``` - Boolean -> String -> a -> a - ``` - */ - warnIfNot = cond: msg: - if cond - then x: x - else warn msg; - - /** - Like the `assert b; e` expression, but with a custom error message and - without the semicolon. - - If true, return the identity function, `r: r`. - - If false, throw the error message. - - Calls can be juxtaposed using function application, as `(r: r) a = a`, so - `(r: r) (r: r) a = a`, and so forth. - - # Inputs - - `cond` - - : 1\. Function argument - - `msg` - - : 2\. Function argument - - # Type - - ``` - bool -> string -> a -> a - ``` - - # Examples - :::{.example} - ## `lib.trivial.throwIfNot` usage example - - ```nix - throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list." - lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays - pkgs - ``` - - ::: - */ - throwIfNot = cond: msg: - if cond - then x: x - else throw msg; - - /** - Like `throwIfNot`, but negated (throw if the first argument is `true`). - - # Inputs - - `cond` - - : 1\. Function argument - - `msg` - - : 2\. Function argument - - # Type - - ``` - bool -> string -> a -> a - ``` - */ - throwIf = cond: msg: - if cond - then throw msg - else x: x; - - /** - Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise. - - # Inputs - - `msg` - - : 1\. Function argument - - `valid` - - : 2\. Function argument - - `given` - - : 3\. Function argument - - # Type - - ``` - String -> List ComparableVal -> List ComparableVal -> a -> a - ``` - - # Examples - :::{.example} - ## `lib.trivial.checkListOfEnum` usage example - - ```nix - let colorVariants = ["bright" "dark" "black"] - in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants; - => - error: color variants: bright, black unexpected; valid ones: standard, light, dark - ``` - - ::: - */ - checkListOfEnum = msg: valid: given: let - unexpected = lib.subtractLists valid given; - in - lib.throwIfNot (unexpected == []) - "${msg}: ${builtins.concatStringsSep ", " (map toString unexpected)} unexpected; valid ones: ${builtins.concatStringsSep ", " (map toString valid)}"; - - info = msg: builtins.trace "INFO: ${msg}"; - - showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings; - - ## Function annotations - - /** - Add metadata about expected function arguments to a function. - The metadata should match the format given by - builtins.functionArgs, i.e. a set from expected argument to a bool - representing whether that argument has a default or not. - - This function is necessary because you can't dynamically create a - function of the `{ a, b ? foo, ... }:` format, but some facilities - like `callPackage` expect to be able to query expected arguments. - - # Type - - ``` - setFunctionArgs : (a -> b) -> Map String Bool -> (a -> b) - ``` - - # Inputs - - `f` - - : 1\. Function argument - - `args` - - : 2\. Function argument - */ - setFunctionArgs = f: args: { - # TODO: Should we add call-time "type" checking like built in? - __functor = self: f; - __functionArgs = args; - }; - - /** - Extract the expected function arguments from a function. - This works both with nix-native `{ a, b ? foo, ... }:` style - functions and functions with args set with `setFunctionArgs`. It - has the same return type and semantics as `builtins.functionArgs`. - - # Type - - ``` - functionArgs : (a -> b) -> Map String Bool - ``` - - # Inputs - - `f` - - : 1\. Function argument - */ - functionArgs = f: - if f ? __functor - then f.__functionArgs or (functionArgs (f.__functor f)) - else builtins.functionArgs f; - - /** - Check whether something is a function or something - annotated with function args. - - # Inputs - - `f` - - : 1\. Function argument - */ - isFunction = f: builtins.isFunction f || (f ? __functor && isFunction (f.__functor f)); - - /** - `mirrorFunctionArgs f g` creates a new function `g'` with the same behavior as `g` (`g' x == g x`) - but its function arguments mirroring `f` (`lib.functionArgs g' == lib.functionArgs f`). - - # Inputs - - `f` - - : Function to provide the argument metadata - - `g` - - : Function to set the argument metadata to - - # Type - - ``` - mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c) - ``` - - # Examples - :::{.example} - ## `lib.trivial.mirrorFunctionArgs` usage example - - ```nix - addab = {a, b}: a + b - addab { a = 2; b = 4; } - => 6 - lib.functionArgs addab - => { a = false; b = false; } - addab1 = attrs: addab attrs + 1 - addab1 { a = 2; b = 4; } - => 7 - lib.functionArgs addab1 - => { } - addab1' = lib.mirrorFunctionArgs addab addab1 - addab1' { a = 2; b = 4; } - => 7 - lib.functionArgs addab1' - => { a = false; b = false; } - ``` - - ::: - */ - mirrorFunctionArgs = f: let - fArgs = functionArgs f; - in - g: setFunctionArgs g fArgs; - - /** - Turns any non-callable values into constant functions. - Returns callable values as is. - - # Inputs - - `v` - - : Any value - - # Examples - :::{.example} - ## `lib.trivial.toFunction` usage example - - ```nix - nix-repl> lib.toFunction 1 2 - 1 - - nix-repl> lib.toFunction (x: x + 1) 2 - 3 - ``` - - ::: - */ - toFunction = v: - if isFunction v - then v - else k: v; - - /** - Convert a hexadecimal string to it's integer representation. - - # Type - - ``` - fromHexString :: String -> Int - ``` - - # Examples - :::{.example} - ## `lib.trivial.fromHexString` usage examples - ```nix - fromHexString "FF" - => 255 - - fromHexString "0x7fffffffffffffff" - => 9223372036854775807 - ``` - ::: - */ - fromHexString = str: let - match = builtins.match "(0x)?([0-7]?[0-9A-Fa-f]{1,15})" str; - in - if match != null - then (fromTOML "v=0x${builtins.elemAt match 1}").v - else - # TODO: Turn this into a `throw` in 26.05. - assert lib.warn "fromHexString: ${ - lib.generators.toPretty {} str - } is not a valid input and will be rejected in 26.05" - true; let - noPrefix = lib.strings.removePrefix "0x" (lib.strings.toLower str); - in - (fromTOML "v=0x${noPrefix}").v; - - /** - Convert the given positive integer to a string of its hexadecimal - representation. - - # Examples - :::{.example} - ## `lib.trivial.toHexString` usage example - - ```nix - toHexString 0 => "0" - - toHexString 16 => "10" - - toHexString 250 => "FA" - ``` - ::: - */ - toHexString = let - hexDigits = { - "10" = "A"; - "11" = "B"; - "12" = "C"; - "13" = "D"; - "14" = "E"; - "15" = "F"; - }; - toHexDigit = d: - if d < 10 - then toString d - else hexDigits.${toString d}; - in - i: lib.concatMapStrings toHexDigit (toBaseDigits 16 i); - - /** - `toBaseDigits base i` converts the positive integer `i` to a list of its - digits in the given base. - - # Inputs - - `base` - - : 1\. Function argument - - `i` - - : 2\. Function argument - - # Examples - :::{.example} - ## `lib.trivial.toBaseDigits` - - ```nix - toBaseDigits 10 123 => [ 1 2 3 ] - - toBaseDigits 2 6 => [ 1 1 0 ] - - toBaseDigits 16 250 => [ 15 10 ] - ``` - ::: - */ - toBaseDigits = base: i: let - go = i: - if i < base - then [i] - else let - r = i - ((i / base) * base); - q = (i - r) / base; - in - [r] ++ go q; - in - assert (isInt base); - assert (isInt i); - assert (base >= 2); - assert (i >= 0); - lib.reverseList (go i); -} diff --git a/nib/sys.bak/TODO_TODO_TODO.nix b/nib/sys.bak/TODO_TODO_TODO.nix deleted file mode 100644 index 9d81b52..0000000 --- a/nib/sys.bak/TODO_TODO_TODO.nix +++ /dev/null @@ -1,74 +0,0 @@ -# REF: https://github.com/numtide/flake-utils/blob/main/allSystems.nix -# XXX: TODO: Provide access to ALL of these systems -[ - "aarch64-darwin" - "aarch64-genode" - "aarch64-linux" - "aarch64-netbsd" - "aarch64-none" - "aarch64_be-none" - "arm-none" - "armv5tel-linux" - "armv6l-linux" - "armv6l-netbsd" - "armv6l-none" - "armv7a-darwin" - "armv7a-linux" - "armv7a-netbsd" - "armv7l-linux" - "armv7l-netbsd" - "avr-none" - "i686-cygwin" - "i686-darwin" - "i686-freebsd13" - "i686-genode" - "i686-linux" - "i686-netbsd" - "i686-none" - "i686-openbsd" - "i686-windows" - "javascript-ghcjs" - "m68k-linux" - "m68k-netbsd" - "m68k-none" - "microblaze-linux" - "microblaze-none" - "microblazeel-linux" - "microblazeel-none" - "mips64el-linux" - "mipsel-linux" - "mipsel-netbsd" - "mmix-mmixware" - "msp430-none" - "or1k-none" - "powerpc-netbsd" - "powerpc-none" - "powerpc64-linux" - "powerpc64le-linux" - "powerpcle-none" - "riscv32-linux" - "riscv32-netbsd" - "riscv32-none" - "riscv64-linux" - "riscv64-netbsd" - "riscv64-none" - "rx-none" - "s390-linux" - "s390-none" - "s390x-linux" - "s390x-none" - "vc4-none" - "wasm32-wasi" - "wasm64-wasi" - "x86_64-cygwin" - "x86_64-darwin" - "x86_64-freebsd13" - "x86_64-genode" - "x86_64-linux" - "x86_64-netbsd" - "x86_64-none" - "x86_64-openbsd" - "x86_64-redox" - "x86_64-solaris" - "x86_64-windows" -] diff --git a/nib/sys.bak/default.nix b/nib/sys.bak/default.nix deleted file mode 100644 index 5f7ba35..0000000 --- a/nib/sys.bak/default.nix +++ /dev/null @@ -1,42 +0,0 @@ -{nib, ...}: let - crossLists = nib.std.crossLists; - identityAttrsMany = nib.std.identityAttrsMany; - - # === Internal Helper Functions === - toSystemName = arch: platform: "${arch}-${platform}"; - listsToSystemNames = archs: platforms: - crossLists (arch: platform: toSystemName arch platform) - [ - (builtins.attrValues archs) - (builtins.attrValues platforms) - ]; -in rec { - # REF: https://github.com/nix-systems/nix-systems - archs = identityAttrsMany [ - "x86_64" - "aarch64" - "riscv64" - ]; - - # REF: https://github.com/nix-systems/nix-systems - platforms = identityAttrsMany [ - "linux" - "darwin" - ]; - - # Nix System Identifier Lists - Default Supported Systems - # systems = systemsDefault; - systems.default = systems.x86_64 // systems.aarch64; - - # Nix System Identifier Lists - All Potential Systems - systems.all = listsToSystemNames archs platforms; - - # Nix System Identifier Lists - Platform Specific - systems.linux = listsToSystemNames archs [platforms.linux]; - systems.darwin = listsToSystemNames archs [platforms.darwin]; - - # Nix System Identifier Lists - Architecture Specific - systems.x86_64 = listsToSystemNames [archs.x86_64] platforms; - systems.aarch64 = listsToSystemNames [archs.aarch64] platforms; - systems.riscv64 = listsToSystemNames [archs.riscv64] platforms; -} diff --git a/nib/sys.nix b/nib/sys.nix deleted file mode 100644 index b487663..0000000 --- a/nib/sys.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ - systems, - nib, - ... -}: let - std = nib.std; -in { - # === External Functions === - withPkgs = repo: config: system: - import repo { - inherit system; - } - // config; - - mkSys = input: let - # function taking a system as argument - pkgsFor = input.pkgs; - in { - inherit pkgsFor; - forAllSystems = f: - std.genAttrs systems ( - system: f system (pkgsFor system) - ); - }; - - mkUSys = input: let - # functions taking a system as argument - pkgsFor = input.pkgs; - upkgsFor = input.upkgs; - in { - inherit pkgsFor upkgsFor; - forAllSystems = f: - std.genAttrs systems ( - system: f system (pkgsFor system) (upkgsFor system) - ); - }; -} diff --git a/nib/types/default.nix b/nib/types/default.nix deleted file mode 100644 index eb2e71c..0000000 --- a/nib/types/default.nix +++ /dev/null @@ -1,21 +0,0 @@ -{nib, ...} @ args: let - fault = import ./fault.nix args; - maybe = import ./maybe.nix args; - res = import ./res.nix args; - terminal = import ./terminal.nix args; -in - nib.std.mergeAttrsList [ - # submodule is included directly to this module (ie self.myFunc) - fault - maybe - res - terminal - - rec { - # TODO - isAlgebraic = T: false; - - isList = T: !isAlgebraic T && builtins.isList T; - isAttrs = T: !isAlgebraic T && builtins.isAttrs T; - } - ] diff --git a/nib/types/fault.nix b/nib/types/fault.nix deleted file mode 100644 index 8abb52f..0000000 --- a/nib/types/fault.nix +++ /dev/null @@ -1,18 +0,0 @@ -{nib, ...}: rec { - # Fault Monad - # Wrapper around an error (ie builtins.abort) - Fault = error: { - _error_ = error; - }; - - # Pattern Matching - isFault = T: builtins.attrNames T == ["_error_"]; - - # Unwrap (Monadic Return Operation) - unwrapFault = T: - assert isFault T || nib.panic.badType "Fault" T; - T._error_; - - # Map (Monadic Bind Operation) - mapFault = f: T: Fault (f (unwrapFault T)); -} diff --git a/nib/types/maybe.nix b/nib/types/maybe.nix deleted file mode 100644 index ea13f4b..0000000 --- a/nib/types/maybe.nix +++ /dev/null @@ -1,110 +0,0 @@ -{nib, ...}: let - findFirst = nib.std.findFirst; - # TODO: try get enum generation working (and other type constructors) - # Maybe = mkEnum "nib::Maybe" { - # Some = mkEnumVariant {value = "nix::String";}; - # None = mkEnumVariant {}; - # }; - # TODO: you could even simplify this and pregenerate - # TODO: monadic operations by defining: - # mkMonad = mkEnum ... (blah blah blah) - # - # NOTE: internal view: - # NOTE: sum == enum - # NOTE: product == struct - # NOTE: terminal == literal/epsilon (in EBNF/Extended Backus-Naur form) - # Maybe = { - # # "adt" aka "algebraic data type" - # _adt_ = nib.types.adt.sum; - # _type_ = "Maybe"; # full type signature is "nib::Maybe" - # _vars_ = [ - # { - # _adt_ = nib.types.adt.product; - # _type_ = "Some"; # type signature is "nib::Maybe::Some" - # _body_ = [ - # # the name "value" was chosen by the user, its not inherit to nib - # value = { - # _adt_ = nib.types.adt.terminal; - # # nib.typeSig simply parses the string by splitting on "::" and forming a list - # _sig_ = nib.typeSig "nix::String"; - # }; - # ]; - # }; - # { - # _adt_ = nib.types.adt.terminal; - # _type_ = "None"; # type signature is "nib::Maybe::None" - # _sig_ = nib.typeSig "nix::Null"; - # }; - # ]; - # None = { - # - # }; - # _body_ = { - # _some_ = some; # allows _value_ to be null (yuck!!) - # _value_ = value; - # }; - # }; - # - # TODO: you could enforceType types as follows - # DEFINE: enforce = pred: var: - # DEFINE: assert (pred var) || throw "..."; var; - # DEFINE: enforceType = type: - # DEFINE: enforce (var: nib.typeOf var == type) - # value: let - # # NOTE: var is either a fixed-point of enforceType or fails - # # NOTE: either way you don't need to worry about a recursive definition! - # var = enforceType "nib::Maybe" var; - # in { ... } -in rec { - # Maybe (Option) Monad - Maybe = some: value: { - _some_ = some; # allows _value_ to be null (yuck!!) - _value_ = value; - }; - Some = Maybe true; - None = Maybe false null; - - # Pattern Matching (unsafe and safe variants) - isMaybe = T: builtins.attrNames T == ["_some_" "_value_"]; - isSome' = T: isMaybe T && T._some_; - isSome = T: - assert isMaybe T || nib.panic.badType "Maybe" T; - isSome' T; - isNone' = T: isMaybe T && !T._some_; - isNone = T: - assert isMaybe T || nib.panic.badType "Maybe" T; - isNone' T; - - # TODO: ensure you check isNone if isSome fails (otherwise it could be another type!) - # Unwrap (Monadic Return Operation) - unwrapMaybe = f: g: T: - if isSome T - then f T._value_ - else g T._value_; - unwrapSome = unwrapMaybe (v: v); - unwrapNone = f: unwrapMaybe f (v: v); - - # Map (Monadic Bind Operation) - mapMaybe = f: unwrapMaybe (v: Some (f v)) (_: None); - # NOTE: yes this does nothing, its only here so I don't forget - # NOTE: (ie when pregenerating monadic operations with a custom ADT module) - mapSome = mapMaybe; - - # Conditionals - someOr = f: T: - if isSome T - then T - else f T; - - noneOr = f: T: - if isNone T - then T - else f T; - - firstSome = findFirst isSome' None; - - nullableToMaybe = x: - if x == null - then None - else Some x; -} diff --git a/nib/types/res.nix b/nib/types/res.nix deleted file mode 100644 index 42e9afd..0000000 --- a/nib/types/res.nix +++ /dev/null @@ -1,51 +0,0 @@ -{nib, ...}: let - findFirst = nib.std.findFirst; -in rec { - # Res (Result) Monad - Res = success: value: { - _success_ = success; - _value_ = value; - }; - Ok = Res true; - Ok' = Ok "ok"; - Err = Res false; - Err' = Err "err"; - - # Pattern Matching - isRes = R: builtins.attrNames R == ["_success_" "_value_"]; - isOk' = R: isRes R && R._success_; - isOk = R: - assert isRes R || nib.panic.badType "Res" R; - isOk' R; - isErr' = R: isRes R && !R._success_; - isErr = R: - assert isRes R || nib.panic.badType "Res" R; - isErr' R; - - # Unwrap (Monadic Return Operation) - unwrapRes = f: g: R: - if isOk R - then f R._value_ - else g R._value_; - unwrapOk = unwrapRes (v: v); - unwrapErr = f: unwrapRes f (v: v); - - # Map (Monadic Bind Operation) - mapRes = f: g: unwrapRes (v: Ok (f v)) (v: Err (f v)); - mapOk = f: mapRes f (v: v); - mapErr = f: mapRes (v: v) f; - - # Conditionals - okOr = f: R: - if isOk R - then R - else f R; - - errOr = f: R: - if isErr R - then R - else f R; - - # Standard Helpers - firstErr = findFirst isErr' Ok'; -} diff --git a/nib/types/terminal.nix b/nib/types/terminal.nix deleted file mode 100644 index 9e996ea..0000000 --- a/nib/types/terminal.nix +++ /dev/null @@ -1,22 +0,0 @@ -{nib, ...}: rec { - # Terminal Monad - # Wrapper around a value (preserves lazy eval for the value) - Terminal = value: { - _nbtype_ = "nib::Terminal"; - _value_ = value; - }; - - # Pattern Matching - isTerminal = T: - builtins.isAttrs T - && builtins.attrNames T == ["_nbtype_" "_value_"] - && T._nbtype_ == "nib::Terminal"; - - # Unwrap (Monadic Return Operation) - unwrapTerminal = T: - assert isTerminal T || nib.panic.badType "Terminal" T; - T._value_; - - # Map (Monadic Bind Operation) - mapTerminal = f: T: Terminal (f (unwrapTerminal T)); -} diff --git a/nib/typesystem.nix b/nib/typesystem.nix deleted file mode 100644 index 7f2d2e2..0000000 --- a/nib/typesystem.nix +++ /dev/null @@ -1,9 +0,0 @@ -{...}: rec { - isType = type: T: type == typeOf T; - isSameType = T1: T2: typeOf T1 == typeOf T2; - - # TODO - typeOf = builtins.typeOf; - # TODO - typeName = typeOf; -}