diff options
author | Vincent Ambo <tazjin@google.com> | 2019-08-24T13·10+0100 |
---|---|---|
committer | Vincent Ambo <tazjin@google.com> | 2019-08-28T13·36+0100 |
commit | f6635fec982ecf892f77dde82568689631932d85 (patch) | |
tree | fad487487f543d066c67d9244a23d0056b7f62c8 | |
parent | ef4ded7b98f503b6d39c9e2fb843fb8de94279d9 (diff) |
feat: Add rough initial version of sum types
Sum types are represented as attribute sets with a single key in them.
-rw-r--r-- | yants.nix | 16 | ||||
-rw-r--r-- | z-yants-tests.nix | 17 |
2 files changed, 32 insertions, 1 deletions
diff --git a/yants.nix b/yants.nix index 51bc5fe5c433..26c5b317c9fb 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 e089aab4670a..f468f61322ec 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"); |