diff --git a/default.nix b/default.nix index 8d0f983..70fe1a8 100644 --- a/default.nix +++ b/default.nix @@ -68,7 +68,7 @@ is = contract { message = s: "Value should be of type `${s.type}':"; }; # TODO I'm not sure if this would be really handy: # FunctionArgs = args: f: args == builtins.functionArgs f; # ... because I would prefer something like: -fn = Args: f: x: f (is (def Args) x); +fn = arg: f: x: f (is (def arg) x); /* Force the concrete evaluation of a contract or any datatype */ strict = e: builtins.deepSeq e e; @@ -135,6 +135,10 @@ match = regex: # FIXME check if `regex` is of `Regex` type! # From https://www.rfc-editor.org/rfc/rfc3986#page-50 Url = match ''^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?''; +Drv = declare { name = "Derivation"; } { type = "derivation"; }; +Maybe = declare { name = "Maybe"; } (x: enum [ Null x ]); +Unit = declare { name = "{}"; } { }; # TODO: This just behaves like Set type ... + /* *** Some type ideas for the future *** */ Hash = TODO; # FIXME SRI hashes used by Nix :) Regex = TODO; # It would be nice to check if a RegEx is valid ... @@ -146,7 +150,44 @@ SemVer = TODO; # ... or if a software version is in SemVer format! # This is internal mixture that helps to have declared types available here: prelude = (builtins.mapAttrs (n: _: declare { name = n; } types.${n}) types); +# Compatibility with https://code.tvl.fyi/about/nix/yants :) +# blob: cb9fc08287fb1f81159d996947c0aaf1cc1672be + +yants = with prelude; +let opt = x: if isString arg then (declare { name = x; }) else (def arg); in +rec { + any = Any; + attrs = setOf; + bool = Bool; + + # FIXME: This buggy and not yet understand how to write it correctly ... + # FIXME: Should declare it as { name = "λ :: A -> B -> C" }? + defun = args: f: a: let x = builtins.head args; xs = builtins.tail args; in + fn x (if builtins.length args > 1 then (defun xs f) else (f a)); + + drv = Drv; + either = t1: t2: enum [ t1 t2 ]; + eitherN = enum; + + # FIXME: Does not support pattern matching as .match "foo" { foo = ...; } + enum = opt enum; + + float = Float; + function = enum [ Lambda Functor ]; + int = Int; + list = listOf; + null = Null; + option = Maybe; + path = Path; + restrict = name: pred: t: x: contract {name = name; } (pred (def t x)); + string = String; + struct = opt; + sum = opt both; + type = Type; + unit = Unit; +}; + in prelude // { # Explicitly choose what would be our library interface (and eventually not) - inherit declare def default contract is fn strict; + inherit declare def default contract is fn strict yants; }