about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--yants.nix16
-rw-r--r--z-yants-tests.nix17
2 files changed, 32 insertions, 1 deletions
diff --git a/yants.nix b/yants.nix
index 51bc5fe5c4..26c5b317c9 100644
--- a/yants.nix
+++ b/yants.nix
@@ -74,6 +74,20 @@ with builtins; let
        else actions."${__functor { inherit name check; } x}";
   };
 
+  sum = name: values: let
+    isVariant = x:
+      let name = elemAt (attrNames x) 0;
+      in if hasAttr name values
+        then values."${name}".check x."${name}"
+        else false;
+    check = x: isAttrs x && length (attrNames x) == 1 && isVariant x;
+  in {
+    inherit name values check;
+    __functor = self: x: if self.check x
+      then x
+      else throw "'${toPretty x}' is not a valid variant of '${name}'";
+  };
+
   mkFunc = sig: f: {
     inherit sig;
     __toString = self: foldl' (s: t: "${s} -> ${t.name}")
@@ -111,4 +125,4 @@ in (typeSet [
   )) true (attrValues v))))
 
   (poly2 "either" (t1: t2: v: t1.check v || t2.check v))
-]) // { inherit struct enum defun; }
+]) // { inherit struct enum sum defun; }
diff --git a/z-yants-tests.nix b/z-yants-tests.nix
index e089aab467..f468f61322 100644
--- a/z-yants-tests.nix
+++ b/z-yants-tests.nix
@@ -46,6 +46,23 @@ deepSeq rec {
     green = throw "It should not be green!";
   };
 
+  # Test sum type definitions
+  creature = sum "creature" {
+    human = struct {
+      name = string;
+      age = option int;
+    };
+
+    pet = enum "pet" [ "dog" "lizard" "cat" ];
+  };
+
+  testSum = creature {
+    human = {
+      name = "Brynhjulf";
+      age = 42;
+    };
+  };
+
   # Test curried function definitions
   func = defun [ string int string ]
   (name: age: "${name} is ${toString age} years old");