Unlocking the Magic of Monads with Java 8
Transcript of Unlocking the Magic of Monads with Java 8
![Page 1: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/1.jpg)
Unlocking the Magic of Monads with Java 8
Oleg Šelajev @shelajev
ZeroTurnaround
![Page 2: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/2.jpg)
whoami
@shelajev
![Page 3: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/3.jpg)
![Page 4: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/4.jpg)
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
![Page 5: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/5.jpg)
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
![Page 6: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/6.jpg)
![Page 7: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/7.jpg)
Java 8: lambda recap
@FunctionalInterfacepublic interface Function<T, R> { R apply(T t); }
![Page 8: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/8.jpg)
Java 8: lambda recap
Function<String, Integer> f = Integer::valueOf;
![Page 9: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/9.jpg)
Java 8: lambda recap
String prefix = “JavaDay Kiyv: "; Function<String, Integer> f = (str) -> { System.out.println(prefix + str); return str.hashCode(); };
![Page 10: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/10.jpg)
Death by 1000 tutorials
![Page 11: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/11.jpg)
Problem driven education
![Page 12: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/12.jpg)
Problem statement
![Page 13: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/13.jpg)
Problem statementobject.methodCall(arg, () -> { // callback object.methodCall(arg, () -> { // callback object.methodCall(arg, () -> { // … }); }); });
![Page 14: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/14.jpg)
Problem statementobject.interact("option1", () -> { object.doThing("fast", () -> { if(wasSuccessful()) { object.celebrate(100, TimeUnit.SECONDS, () -> { System.out.println("Back to work"); }); } else { object.beSad(":(", () -> { System.out.println("Still back to work"); }); }); });
![Page 15: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/15.jpg)
Problem statementobject.interact("option1", () -> { object.doThing("fast", () -> { if(wasSuccessful()) { object.celebrate(100, TimeUnit.SECONDS, () -> { System.out.println("Back to work"); }); } else { object.beSad(":(", () -> { System.out.println("Still back to work"); }); }); });
![Page 16: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/16.jpg)
Wishful thinking
object.interact("option1") .then((o) -> o.doThing("fast")) .then((o) -> o.celebrate(100, SECONDS, () -> { System.out.println("Back to work”); })) .or((o) -> o.beSad(":("));
![Page 17: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/17.jpg)
Wishful thinking
object.interact("option1") .then((o) -> o.doThing("fast")) .then((o) -> o.celebrate(100, SECONDS, () -> { System.out.println("Back to work”); })) .or((o) -> o.beSad(":("));
![Page 18: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/18.jpg)
Type: async result
java.util.concurrent.Future<V>
boolean isDone(); V get() … V get(long timeout, TimeUnit unit)
![Page 19: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/19.jpg)
Type: async result
java.util.concurrent.Future<V>
boolean isDone(); V get() … V get(long timeout, TimeUnit unit)
Can we do
better?
![Page 20: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/20.jpg)
Monads to the rescue
![Page 21: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/21.jpg)
Monads to the rescue
![Page 22: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/22.jpg)
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.
![Page 23: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/23.jpg)
It is known
Every cook can understand, compile and use monads…
V. Lenin (1923)
![Page 24: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/24.jpg)
![Page 25: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/25.jpg)
![Page 26: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/26.jpg)
Monads: intuition
wrapping things
chaining functions on those things
monad is a type
![Page 27: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/27.jpg)
![Page 28: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/28.jpg)
Wrapping: return / pure
Take instance of “a”, return: “m a”
Constructor / Factory method
![Page 29: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/29.jpg)
Pure in Java
public interface Monad<V> { Monad<V> pure(V value); }
![Page 30: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/30.jpg)
Chaining: bind / (>>=)
take:
monad: “m a”
function: “a => m b”
return: monad “m b”
![Page 31: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/31.jpg)
Bind in Java
public interface Monad<V> { Monad<V> pure(V v); <R> Monad<R> bind(Function<V, Monad<R>> f); }
![Page 32: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/32.jpg)
Hacking time
Promise<V> - result of async computation
Kinda like Future<V>
supports chaining functions: bind
![Page 33: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/33.jpg)
Imagined Promise<V>
existing Future operations + finish: p.invoke(V v);
add callback: p.onRedeem(Action<Promise<V>> callback);
![Page 34: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/34.jpg)
Promise<V>: pure
public <V> Promise<V> pure(final V v) { Promise<V> p = new Promise<>(); p.invoke(v); return p; }
![Page 35: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/35.jpg)
Promise<V>: bindpublic <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; }
![Page 36: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/36.jpg)
Promise<V>: bindpublic <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; }
![Page 37: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/37.jpg)
Promise<V>: bindpublic <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;}
![Page 38: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/38.jpg)
Promise<V>: bindpublic <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;}
![Page 39: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/39.jpg)
Promise<V>: get
public V get() throws InterruptedException, ExecutionException { if (exception != null) { throw new ExecutionException(exception); } return result; }
![Page 40: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/40.jpg)
ExamplePromise<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());
![Page 41: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/41.jpg)
Checkpoint
Promise - represents async computation
Handling values AND exceptions
Chaining of functions
![Page 42: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/42.jpg)
Wait, is that it?
Monad vs. Instance of monad
![Page 43: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/43.jpg)
Typeclass? Higher functions?
Common API
Generic functions over all monads
![Page 44: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/44.jpg)
Greatness
Common operations for Monads
sequence, zip
Limited under parametrised polymorphism in Java
![Page 45: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/45.jpg)
Greatness
Common operations for Monads
sequence, zip
Sequence of promises => joined asynch ops
Sequence of elephants => a chain of them
![Page 46: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/46.jpg)
Sequence
Monad<List<V>> sequence(Monad<V>... monads);
![Page 47: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/47.jpg)
Greatness
Common operations for Monads
sequence, zip
Limited under parametrised polymorphism in Java
![Page 48: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/48.jpg)
Monad in Java
public interface Monad<V> { Monad<V> pure(V v); <R> Monad<R> bind(Function<V, Monad<R> f); V get(); }
![Page 49: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/49.jpg)
One does not simply call oneself a monad!
![Page 50: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/50.jpg)
![Page 51: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/51.jpg)
Laws (don’t be scared)
return a >>= f ≡ f a
m >>= return ≡ m
(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
![Page 52: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/52.jpg)
Left identity
pure(v).bind(f) ≡ f.apply(v)
![Page 53: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/53.jpg)
Right identity
m.bind(m::pure) ≡ m
![Page 54: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/54.jpg)
Associativity
m.bind(f).bind(g) ≡ m.bind(
(v) -> f.apply(v).bind(g))
![Page 55: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/55.jpg)
Some platforms have it easy
Referential transparency
Partial application
≡ is easy
![Page 56: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/56.jpg)
Mortal platforms
No referential transparency
f.apply(v) != f.apply(v)
equals() + hashcode()
![Page 57: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/57.jpg)
Defining ≡ for Java
Side effects are similar
m.get() observes the same values
values or exceptions
![Page 58: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/58.jpg)
Promise: left identityFunction<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());
![Page 59: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/59.jpg)
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()));
![Page 60: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/60.jpg)
Quality software
java.util.concurrent.CompletableFuture
thenApply(Function / Consumer / etc)
thenApplyAsync(Function / etc)
Async => FJP.common()
![Page 62: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/62.jpg)
![Page 63: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/63.jpg)
Optional purestatic <T> Optional<T> of(T value) { return new Optional<>(value); }
static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }
![Page 64: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/64.jpg)
Optional bindpublic<U> Optional<U> flatMap(Function<T, Optional<U>> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Objects.requireNonNull(mapper.apply(value)); } }
![Page 65: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/65.jpg)
Optional bindpublic<U> Optional<U> map(Function<T, U> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Optional.ofNullable(mapper.apply(value)); } }
![Page 66: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/66.jpg)
![Page 67: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/67.jpg)
![Page 68: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/68.jpg)
![Page 71: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/71.jpg)
Minority report
Alternative definition of Monads:
fmap :: (a -> b) -> f a -> f b
join :: m (m a) -> m a
![Page 72: Unlocking the Magic of Monads with Java 8](https://reader034.fdocuments.in/reader034/viewer/2022052418/589fe1941a28abf3238b4fb1/html5/thumbnails/72.jpg)
Exercises
Implement (>>=) in terms of fmap and join.
Now implement join and fmap in terms of (>>=)and return.