add panic.nix and assertions to type checks

This commit is contained in:
Emile Clark-Boman 2025-12-14 22:41:17 +10:00
parent fd008cd2e1
commit ea01dcc827
5 changed files with 44 additions and 25 deletions

View file

@ -6,11 +6,12 @@
std = mkMod ./std;
types = mkMod ./types;
parse = mkMod ./parse;
panic = mkMod ./panic.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 parse;}
{inherit std types panic parse;}
# submodule is included directly to this module (ie self.myFunc)

4
nib/panic.nix Normal file
View file

@ -0,0 +1,4 @@
{...}: {
badType = expect: x:
throw "Expected type ${expect} but got ${builtins.typeOf x}.";
}

View file

@ -1,4 +1,4 @@
{...}: rec {
{nib, ...}: rec {
# Fault Monad
# Wrapper around an error (ie builtins.abort)
Fault = error: {
@ -6,11 +6,13 @@
};
# Pattern Matching
isFault = F: builtins.attrNames F == ["_error_"];
isFault = T: builtins.attrNames T == ["_error_"];
# Unwrap (Monadic Return Operation)
unwrapFault = F: F._error_;
unwrapFault = T:
assert isFault T || nib.panic.badType "Fault" T;
T._error_;
# Map (Monadic Bind Operation)
mapFault = f: F: Fault (f (unwrapFault F));
mapFault = f: T: Fault (f (unwrapFault T));
}

View file

@ -62,28 +62,34 @@ in rec {
_some_ = some; # allows _value_ to be null (yuck!!)
_value_ = value;
};
Some = value: Res true value;
Some = Res true;
None = Maybe false null;
# Pattern Matching
# Pattern Matching (unsafe and safe variants)
isMaybe = T: builtins.attrNames T == ["_some_" "_value_"];
isSome = T: isMaybe T && T._some_;
isNone = T: isMaybe T && !T._some_;
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: T:
if isSome T
then Some (f T._value_)
else None;
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 = f: mapMaybe f;
mapSome = mapMaybe;
# Conditionals
someOr = f: T:
@ -96,7 +102,7 @@ in rec {
then T
else f T;
firstSome = findFirst isSome None;
firstSome = findFirst isSome' None;
nullableToMaybe = x:
if x == null

View file

@ -6,28 +6,34 @@ in rec {
_success_ = success;
_value_ = value;
};
Ok = value: Res true value;
Ok = Res true;
Ok' = Ok "ok";
Err = value: Res false value;
Err = Res false;
Err' = Err "err";
# Pattern Matching
isRes = R: builtins.attrNames R == ["_success_" "_value_"];
isOk = R: isRes R && R._success_;
isErr = R: isRes R && !R._success_;
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 = f: unwrapRes (R: R._value_) f;
unwrapErr = f: unwrapRes f (R: R._value_);
unwrapOk = unwrapRes (v: v);
unwrapErr = f: unwrapRes f (v: v);
# Map (Monadic Bind Operation)
mapRes = f: g: unwrapRes (R: Ok (f R)) (R: Err (f R));
mapOk = f: mapRes f (x: x);
mapErr = f: mapRes (x: x) f;
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:
@ -41,5 +47,5 @@ in rec {
else f R;
# Standard Helpers
firstErr = findFirst isErr Ok';
firstErr = findFirst isErr' Ok';
}