feat: Add rough initial version of sum types

Sum types are represented as attribute sets with a single key in them.
This commit is contained in:
Vincent Ambo 2019-08-24 14:10:41 +01:00
parent ef4ded7b98
commit f6635fec98
2 changed files with 32 additions and 1 deletions

View file

@ -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; }

View file

@ -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");