FEATURE: Make our monadic maybe a little more useful now.

This commit is contained in:
Jeremy Wall 2019-02-24 08:33:20 -06:00
parent ec8c75f866
commit 68790520d4
2 changed files with 38 additions and 23 deletions

View File

@ -1,17 +1,32 @@
// maybe is our monadic optional. It wraps a value that may or may not be the empty
// type NULL. It exports three operations.
//
// * do - runs a user provided function of one argument on the value.
// Returns a maybe wrapped result.
//
// * is_null - a function with no arguments that returns true if the value is
// NULL and false if it is not.
//
// * unwrap - returns the wrapped value from the maybe.
//
// * expect - Throws a compile error if the value is NULL.
let maybe = module{
val = NULL,
} => {
let do = func (op) => select (mod.val != NULL), NULL, {
true = op(mod.val),
};
};
let if = module{
test = false,
} => {
let do = func (op, arg) => select mod.test, arg, {
true = op(arg),
} => ({do=do, is_null=is_null, unwrap=unwrap, expect=expect}) {
let maybe = import "std/functional.ucg".maybe;
let do = func (op) => select (mod.val != NULL), maybe{val=NULL}, {
true = maybe{val=op(mod.val)},
};
let is_null = func() => mod.val == NULL;
let unwrap = func() => mod.val;
let expect = func(msg) => select mod.val != NULL, fail msg, {
true = mod.val,
};
};
// identity is the identity function.
let identity = func (arg) => arg;

View File

@ -1,28 +1,28 @@
let t = (import "std/testing.ucg").asserts{};
let f = (import "std/functional.ucg");
let t = import "std/testing.ucg".asserts{};
let f = import "std/functional.ucg";
let op = func (arg) => arg{foo="bar"};
assert t.equal{
left = f.maybe{val=NULL}.do(op),
left = f.maybe{val=NULL}.do(op).unwrap(),
right = NULL,
};
assert t.equal{
left = f.maybe{val={}}.do(op),
right = {foo="bar"},
assert t.ok{
test = f.maybe{val=NULL}.is_null(),
desc = "maybe is null",
};
assert t.ok{
test = f.maybe{val=NULL}.do(op).is_null(),
desc = "maybe is still null after an operation",
};
assert t.equal{
left = f.if{test=true}.do(op, {}),
left = f.maybe{val={}}.do(op).unwrap(),
right = {foo="bar"},
};
assert t.equal{
left = f.if{test=false}.do(op, {}),
right = {},
};
assert t.equal{
left = f.identity("foo"),
right = "foo",