I have been trying to find out how to use Either/Maybe type in Mathematica.
Unfortunately algebraic data type doesn't work very well in Mathematica, some data type definitions are complex.
I have come up a method to use them without define them. I defined Maybe type in functions.
Please notes that there are a couple of incorrect examples in some answers, for instance,
Just[3] + Just[5] == Just[8]
Just[Just[3]] == Just[3]
Maybe type doesn't work like this.
Maybe type is like a box, either it's Just a value, or it's Nothing. Before you use it, you have to unwrap the box and use the value or Nothing directly or indirectly.
Maybe
In:
Maybe[a_] := Just | $Nothing (*Do nothing, it's like a comment*)
fromJust
(*The fromJust function extracts the element out of a Just and throws \
an error if its argument is Nothing.*)
fromJust::argx = "`` is not Just";
fromJust[Just[a_]] := a
fromJust[x_] := Message[fromJust::argx, x]
fromJust[Just[3]]
fromJust[$Nothing]
fromJust[Just[Just[x]]]
fromMaybe
(*The fromMaybe function takes a default value and and Maybe value.If \
the Maybe is Nothing,it returns the default values;otherwise,it \
returns the value contained in the Maybe.*)
fromMaybe::argx = "`` is not Maybe";
fromMaybe[a_, Just[x_]] := x
fromMaybe[a_, $Nothing] := a
fromMaybe[a_, _] := Message[fromMaybe::argx, x]
fromMaybe[0, Just[100]]
fromMaybe[0, $Nothing]
fromMaybe[0, t]
LiftM2
(*Promote a function to a monad,scanning the monadic arguments from \
left to right.For example*)
LiftM2::argx = "Either `` or `` is not Maybe";
LiftM2[f_, Just[a_], Just[b_]] := Just@f[a, b]
LiftM2[f_, $Nothing, _] := $Nothing
LiftM2[f_, _, $Nothing] := $Nothing
LiftM2[f_, x_, y_] := Message[LiftM2::argx, x, y]
LiftM2[#1 + #2 &, Just[3], Just[4]]
LiftM2[#1 + #2 &, Just[5], $Nothing]
LiftM2[#1 + #2 &, t, 3]
Out:

Monad Maybe
The definition of Monad Maybe is simple.
Just[x_] \[CirclePlus] g_ := g[x]
$Nothing \[CirclePlus] g_ := $Nothing
And it's a powerful technique.
If there is a task which has 3 subtasks. Any subtasks can go wrong, it either returns Nothing or a Just value. If any subtask goes wrong, the whole task should be stopped immediately. Before you read further, you could think how you implement it.
Implementation:
ClearAll[f, g, CirclePlus, debug, clean, build, combine]
Just[x_] \[CirclePlus] g_ := g[x]
$Nothing \[CirclePlus] g_ := $Nothing
CirclePlus[f_, g_, h__] := (f \[CirclePlus] g)\[CirclePlus]h
CirclePlus[f_, g_] := f \[CirclePlus] g
debug[name_, Just[x_]] := (Print@name; Just[x])
1
ClearAll[clean, build, combine]
clean[x_] := (Print["Failed: clean"]; $Nothing)
clean[100] \[CirclePlus] build \[CirclePlus] combine
2
ClearAll[clean, build, combine]
clean[x_] := debug[clean, Just[x + 1]]
build[x_] := (Print["Failed: build"]; $Nothing)
clean[100] \[CirclePlus] build \[CirclePlus] combine
3
ClearAll[clean, build, combine]
clean[x_] := debug[clean, Just[x + 1]]
build[x_] := debug[build, Just[x + 1]]
combine[x_] := (Print["Failed: combine"]; $Nothing)
clean[100] \[CirclePlus] build \[CirclePlus] combine
4
ClearAll[clean, build, combine]
clean[x_] := debug[clean, Just[x + 1]]
build[x_] := debug[build, Just[x + 1]]
combine[x_] := debug[combine, Just[x + 1]]
clean[100] \[CirclePlus] build \[CirclePlus] combine
Out:

Notation`
package to implement monadic operators. When I get a chance later today, I may expand this comment to a proper answer, but I think this might get folks thinking in the meantime. $\endgroup$