diff options
author | Profpatsch <mail@profpatsch.de> | 2021-01-23T16·23+0100 |
---|---|---|
committer | Profpatsch <mail@profpatsch.de> | 2021-01-30T15·41+0000 |
commit | e4a7704583812786d90ddc1f3aa639b2866e18e2 (patch) | |
tree | 47f47254f7b198813e151a71410864f50e91e919 /nix/tag/tests.nix | |
parent | 5da7ee9e8a7e3e790963b52f6427027a8823d75a (diff) |
feat(nix): add nix.tag, a way of discriminating via tagged unions r/2166
Introduces the concept of a “tag”, a single-keyed attrset which annotates a nix value with a name. This can be used to implement tagged unions (by implying the list of possible tags is well-known), which has some overlap with how `nix.yants` does it. However, the more fascinating use-case is in concert with a so-called discriminator, `match` and hylomorphisms. The discriminator can take a nix value, and add tags to it based on some predicate. With `match`, we can then use that information to convert the discriminated values again. With `hylo`, we can combine both the “constructive” discriminator step with the “destructive” match step to recursively walk over a nix data structure (based on a description of how to recurse, e.g. through attrset values or list values), and then apply a transformation in one go. Change-Id: Ia335ca8b0881447fbbcb6bcd80f49feb835f1715 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2434 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'nix/tag/tests.nix')
-rw-r--r-- | nix/tag/tests.nix | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/nix/tag/tests.nix b/nix/tag/tests.nix new file mode 100644 index 000000000000..8c9c73807472 --- /dev/null +++ b/nix/tag/tests.nix @@ -0,0 +1,88 @@ +{ depot, lib, verifyTag, discr, discrDef, match, matchLam }: + +let + inherit (depot.nix.runTestsuite) + runTestsuite + assertEq + it + ; + + isTag-test = it "checks whether something is a tag" [ + (assertEq "is Tag" + (verifyTag { foo = "bar"; }) + { + isTag = true; + name = "foo"; + val = "bar"; + errmsg = null; + }) + (assertEq "is not Tag" + (removeAttrs (verifyTag { foo = "bar"; baz = 42; }) ["errmsg"]) + { + isTag = false; + name = null; + val = null; + }) + ]; + + discr-test = it "can discr things" [ + (assertEq "id" + (discr [ + { a = lib.const true; } + ] "x") + { a = "x"; }) + (assertEq "bools here, ints there" + (discr [ + { bool = lib.isBool; } + { int = lib.isInt; } + ] 25) + { int = 25; }) + (assertEq "bools here, ints there 2" + (discr [ + { bool = lib.isBool; } + { int = lib.isInt; } + ] true) + { bool = true; }) + (assertEq "fallback to default" + (discrDef "def" [ + { bool = lib.isBool; } + { int = lib.isInt; } + ] "foo") + { def = "foo"; }) + ]; + + match-test = it "can match things" [ + (assertEq "match example" + (let + success = { res = 42; }; + failure = { err = "no answer"; }; + matcher = { + res = i: i + 1; + err = _: 0; + }; + in { + one = match success matcher; + two = match failure matcher; + }) + { one = 43; + two = 0; }) + (assertEq "matchLam & pipe" + (lib.pipe { foo = 42; } [ + (matchLam { + foo = i: if i < 23 then { small = i; } else { big = i; }; + bar = _: { small = 5; }; + }) + (matchLam { + small = i: "yay it was small"; + big = i: "whoo it was big!"; + }) + ]) + "whoo it was big!") + ]; + +in + runTestsuite "tag" [ + isTag-test + discr-test + match-test + ] |