replace NixType Maybe -> naive type Maybe

This commit is contained in:
Emile Clark-Boman 2026-01-27 11:12:27 +10:00
parent 2807535792
commit c18aef2b32
5 changed files with 84 additions and 82 deletions

View file

@ -34,6 +34,8 @@ let
std = ./std/bootstrap.nix;
types = ./types/bootstrap.nix;
parse = ./parse/bootstrap.nix;
maybe = ./maybe.nix;
trapdoor = ./trapdoor.nix;
}
];

View file

@ -0,0 +1,81 @@
{...}: let
inherit
(builtins)
attrNames
concatStringsSep
isAttrs
typeOf
;
in rec {
# NOTE: Maybe intentionally doesn't use the NixTypes.
# NOTE: Maybe is used to aid in parsing and bootstrapping.
# NOTE: It is intentionally left simple for speed gains.
Maybe = some: value: {
_some = some;
_value = value;
};
Some = Maybe true;
None = Maybe false null;
# Pattern Matching (unsafe and safe variants)
isMaybe = T: attrNames T == ["_some" "_value"];
enfIsMaybe = T: msg: let
throw' = got: throw "${msg}: expected naive type Maybe but got ${got}";
attrs =
attrNames T
|> map (name: "\"${name}\"")
|> concatStringsSep ", ";
in
if isAttrs T
then throw' "attribute set with structure [${attrs}]"
else throw' "value \"${toString T}\" of primitive type \"${typeOf T}\"";
# isSome = T: isMaybe T && T._some;
# isNone = T: isMaybe T && ! T._some;
isSome = T:
assert enfIsMaybe T "isMaybeSome";
T._some;
isNone = T:
assert enfIsMaybe T "isMaybeNone";
! T._some;
# 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 T;
# Conditionals
# someOr = f: T:
# if isSome T
# then T
# else f T;
# noneOr = f: T:
# if isNone T
# then T
# else f T;
boolToMaybe = x:
if x
then Some true
else None;
nullableToMaybe = x:
if x == null
then None
else Some x;
maybeTobool = isSome;
}

View file

@ -12,7 +12,7 @@
;
inherit
(this.types)
(this.maybe)
Some
None
;

View file

@ -2,6 +2,5 @@
# WARNING: this file is strictly for bootstrapping nt
{bootstrap, ...} @ inputs:
bootstrap inputs [
./maybe.nix
./wrap.nix
]

View file

@ -1,80 +0,0 @@
{this, ...}: let
inherit
(this)
ntTrapdoorKey
ntDynamicTrapdoorKey
;
inherit
(this.std)
enfImpls
;
inherit
(this.trapdoor)
mkTrapdoorFn
mkTrapdoorSet
openTrapdoor
;
in {
# NOTE: Maybe is used to simplify parsing Type/Class declarations
# NOTE: and therefore must be implemented manually
Maybe = let
meta = instance: {
sig = "nt::&Maybe";
derive = [];
ops = {};
req = {"nt::&Maybe" = ["unwrap"];};
};
in
mkTrapdoorFn {
default = {
unwrap = T:
assert enfImpls "nt::&Maybe" T "nt::&Maybe.unwrap";
(T |> openTrapdoor ntTrapdoorKey).ops."nt::&Maybe".unwrap;
};
unlock.${ntTrapdoorKey} = meta false;
};
Some = let
meta = instance: {
inherit instance;
sig = "nt::Some";
derive = ["nt::&Maybe"];
ops = {
"nt::&Maybe".unwrap = f: self: f self.${ntDynamicTrapdoorKey}.value;
};
req = {};
};
in
mkTrapdoorFn {
default = value:
mkTrapdoorSet {
unlock = {
${ntTrapdoorKey} = meta true;
${ntDynamicTrapdoorKey} = {
inherit value;
};
};
};
unlock.${ntTrapdoorKey} = meta false;
};
None = let
meta = instance: {
inherit instance;
sig = "nt::None";
derive = ["nt::&Maybe"];
ops = {
"nt::&Maybe".map = f: self: self;
};
req = {};
};
in
mkTrapdoorFn {
default = mkTrapdoorSet ntTrapdoorKey {
unlock = meta true;
};
unlock.${ntTrapdoorKey} = meta false;
};
}