about summary refs log tree commit diff
path: root/nix/tag/tests.nix
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2021-01-23T16·23+0100
committerProfpatsch <mail@profpatsch.de>2021-01-30T15·41+0000
commite4a7704583812786d90ddc1f3aa639b2866e18e2 (patch)
tree47f47254f7b198813e151a71410864f50e91e919 /nix/tag/tests.nix
parent5da7ee9e8a7e3e790963b52f6427027a8823d75a (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.nix88
1 files changed, 88 insertions, 0 deletions
diff --git a/nix/tag/tests.nix b/nix/tag/tests.nix
new file mode 100644
index 0000000000..8c9c738074
--- /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
+  ]