export type Nothing = {
kind: 'Nothing';
};
export type Just = {
kind: 'Just';
value: A;
};
export type Maybe = Just | Nothing;
/*
Create a Maybe with an actual value
*/
export function Just(value: A): Maybe {
return {
kind: 'Just',
value: value,
};
}
/*
Create a Maybe with no value
*/
export function Nothing(): Maybe {
return {
kind: 'Nothing',
};
}
export function isJust(maybe: Maybe): maybe is Just {
switch (maybe.kind) {
case 'Just':
return true;
default:
return false;
}
}
export function isNothing(maybe: Maybe): maybe is Just {
switch (maybe.kind) {
case 'Nothing':
return true;
default:
return false;
}
}
/*
If a maybe has a value, return it.
Otherwise return the provided value
*/
export function withDefault(value: A, maybeValue: Maybe): A {
switch (maybeValue.kind) {
case 'Just':
return maybeValue.value;
default:
return value;
}
}
/*
If a maybe has a value, apply a function to it and return a maybe containing the new value.
Otherwise return Nothing.
*/
export function map(
func: (val: A) => Value,
maybeValue: Maybe
): Maybe {
switch (maybeValue.kind) {
case 'Just':
return Just(func(maybeValue.value));
default:
return maybeValue;
}
}
/*
If both maybes have a value, apply a function to them and return a maybe containing the new value.
Otherwise return Nothing.
*/
export function map2(
func: (firstValue: A, secondValue: B) => Value,
firstMaybeValue: Maybe,
secondMaybeValue: Maybe
): Maybe {
switch (firstMaybeValue.kind) {
case 'Just':
switch (secondMaybeValue.kind) {
case 'Just':
return Just(
func(firstMaybeValue.value, secondMaybeValue.value)
);
default:
return Nothing();
}
default:
return Nothing();
}
}
/*
If all maybes have a value, apply a function to them and return a maybe containing the new value.
Otherwise return Nothing.
*/
export function map3(
func: (firstValue: A, secondValue: B, thirdValue: C) => Value,
firstMaybeValue: Maybe,
secondMaybeValue: Maybe,
thirdMaybeValue: Maybe
): Maybe {
switch (firstMaybeValue.kind) {
case 'Just':
switch (secondMaybeValue.kind) {
case 'Just':
switch (thirdMaybeValue.kind) {
case 'Just':
return Just(
func(
firstMaybeValue.value,
secondMaybeValue.value,
thirdMaybeValue.value
)
);
default:
return Nothing();
}
default:
return Nothing();
}
default:
return Nothing();
}
}
/*
If the maybe has a value, apply a function that turns things into a maybe to it.
Otherwise return Nothing.
*/
export function andThen(
func: (firstValue: A) => Maybe,
maybeValue: Maybe
): Maybe {
switch (maybeValue.kind) {
case 'Just':
return func(maybeValue.value);
default:
return Nothing();
}
}