This code-heavy session demystifies what monads are and outlines reasons why you would even want to introduce them into your code. We’ll take a look at the traditional definition for monads and offer a corresponding type definition in Java. We’ve selected a sample Java 8 implementation of a ‘Promise’ monad, which represents the result of async computation to help us answer practical questions about monads. Also, we'll go over the Laws of Monads and show that you can have a proper monad in Java, if you are brave enough to allow the underlying platform change the rules a bit. PS. You won’t be penalised or ridiculed during this session for your (lack of) Haskell knowledge!
4. What do we want to achieve?
have fun while learning stuff
understand the concept of Monad
get generic constructs for Monads
solve a real-world problem
ignore lack of “ad hoc” polymorphism
and other slightly relevant facts
5. What do we want to achieve?
have fun while learning stuff
understand the concept of Monad
get generic constructs for Monads
solve a real-world problem
ignore lack of “ad hoc” polymorphism
and other slightly relevant facts
6.
7. Java 8: lambda recap
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
8. Java 8: lambda recap
Function<String, Integer> f =
Integer::valueOf;
22. Oh my…
a monad in X is just a
monoid in the
category of
endofunctors of X,
with product ×
replaced by
composition of
endofunctors and unit
set by the identity
endofunctor.
23. It is known
Every cook can
understand,
compile and
use monads…
V. Lenin (1923)
34. Promise<V>: pure
public <V> Promise<V> pure(final V v) {
Promise<V> p = new Promise<>();
p.invoke(v);
return p;
}
35. Promise<V>: bind
public <R> Promise<R> bind(final Function<V, Promise<R>>
function) {
Promise<R> result = new Promise<>();
this.onRedeem(callback -> {
V v = callback.get();
Promise<R> applicationResult = function.apply(v);
applicationResult.onRedeem(c -> {
R r = c.get();
result.invoke(r);
});
return result;
}
36. Promise<V>: bind
public <R> Promise<R> bind(final Function<V, Promise<R>>
function) {
Promise<R> result = new Promise<>();
this.onRedeem(callback -> {
V v = callback.get();
Promise<R> applicationResult = function.apply(v);
applicationResult.onRedeem(c -> {
R r = c.get();
result.invoke(r);
});
return result;
}
37. Promise<V>: bind
public <R> Promise<R> bind(final Function<V, Promise<R>>
function) {
Promise<R> result = new Promise<>();
this.onRedeem(callback -> {
V v = callback.get();
Promise<R> applicationResult = function.apply(v);
applicationResult.onRedeem(c -> {
R r = c.get();
result.invoke(r);
});
return result;
}
38. Promise<V>: bind
public <R> Promise<R> bind(final Function<V, Promise<R>>
function) {
Promise<R> result = new Promise<>();
this.onRedeem(callback -> {
V v = callback.get();
Promise<R> applicationResult = function.apply(v);
applicationResult.onRedeem(c -> {
R r = c.get();
result.invoke(r);
});
return result;
}
39. Promise<V>: get
public V get() throws InterruptedException,
ExecutionException {
if (exception != null) {
throw new ExecutionException(exception);
}
return result;
}
40. Example
Promise<String> p = Async.submit(() -> {
return "hello world";
});
Promise<Integer> result = p.bind(string ->
Promise.pure(Integer.valueOf(string.hashCode())));
System.out.println("HashCode = " + result.get());
57. Defining ≡ for Java
Side effects are similar
m.get() observes the same values
values or exceptions
58. Promise: left identity
Function<Integer, Promise<Boolean>> f =
(x) -> {
return submit(() -> x % 2 == 0);
};
Integer val = new Integer(100);
assertEquals(Promise.pure(val).bind(f).get(),
f.apply(val).get());
59. Promise: right identity
Integer val = new Integer(100000);
Promise<Integer> p =
Promise.pure(val).bind(Promise::pure);
assertEquals(val, p.get());
assertEquals(identityHashCode(val),
identityHashCode(p.get()));