Despite the fact that monads can be implemented in Java, any calculations associated with them are doomed to become a dirty combination of generics and curly braces.
I would say that Java is definitely not a language to use to illustrate their work or to study their meaning and essence. To do this, it is much better to use JavaScript or pay an additional price and learn Haskell.
In any case, I warn you that I just implemented the monad monad using the new Java 8 lambdas . This is definitely a pet project, but it works in a non-trivial test case.
You can find it on my blog , but I will tell you a few details.
The state monad is basically a function from state to pair (state, content) . Usually you provide the state with general type S and content with general type A.
Since Java does not have pairs, we must model them using a certain class, let us call it Scp (state-content pair), which in this case will have the general type Scp<S,A> and the constructor new Scp<S,A>(S state,A content) . After that, we can say that the monadic function will be of type
java.util.function.Function<S,Scp<S,A>>
which is @FunctionalInterface . This means that its one and only implementation method can be called without naming it, passing a lambda expression with the correct type.
The StateMonad<S,A> class is mainly a wrapper around a function. Its constructor can be called, for example. from
new StateMonad<Integer, String>(n -> new Scp<Integer, String>(n + 1, "value"));
The state monad stores the function as an instance variable. Then you need to provide a public method of access to it and pass it to the state. I decided to call it s2scp ("state to state-content pair").
To complete the definition of the monad, you must provide the unit (aka return) and the bind method (aka flatMap). Personally, I prefer to specify the unit as static, and bind is an instance member.
In the case of a state monad, the unit shall be as follows:
public static <S, A> StateMonad<S, A> unit(A a) { return new StateMonad<S, A>((S s) -> new Scp<S, A>(s, a)); }
while bind (as an instance member):
public <B> StateMonad<S, B> bind(final Function<A, StateMonad<S, B>> famb) { return new StateMonad<S, B>((S s) -> { Scp<S, A> currentPair = this.s2scp(s); return famb(currentPair.content).s2scp(currentPair.state); }); }
You have noticed that bind must introduce a generic type B, because it is a mechanism that allows you to bind heterogeneous state monads and gives this and any other monad a wonderful opportunity to move computations from type to type.
I would dwell on Java code here. The complex material is in the GitHub project. Compared to previous versions of Java, lambdas removes many curly braces, but the syntax is still quite confusing.
Just as an aside, I show how a similar state monad code can be written in other major languages. In the case of Scala, bind (which in this case should be called flatMap) reads like
def flatMap[A, B](famb: A => State[S, B]) = new State[S, B]((s: S) => { val (ss: S, aa: A) = this.s2scp(s) famb(aa).s2scp(ss) })
whereas JavaScript bindings are my favorite; 100% functional, meager and average, but, of course, impersonal:
var bind = function(famb){ return state(function(s) { var a = this(s); return famb(a.value)(a.state); }); };
<shameless> I cut a few corners here, but if you are interested in the details, you will find them on my WP blog. </shameless>