+ All Categories
Home > Documents > with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the...

with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the...

Date post: 07-Jul-2020
Category:
Upload: others
View: 3 times
Download: 0 times
Share this document with a friend
63
Unlocking magic of Monads with Java 8 Oleg Šelajev @shelajev ZeroTurnaround
Transcript
Page 1: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Unlocking magic of Monads with Java 8

Oleg Šelajev @shelajev

ZeroTurnaround

Page 2: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Who am I

@shelajev

Page 3: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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 4: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every
Page 6: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Java 8: lambda recap

@FunctionalInterfacepublic interface Function<T, R> { R apply(T t); }

Page 7: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Java 8: lambda recap

Function<String, Integer> f = Integer::valueOf;

Page 8: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Java 8: lambda recap

String prefix = “JFokus: "; Function<String, Integer> f = (str) -> { System.out.println(prefix + str); return str.hashCode(); };

Page 9: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Death by 1000 tutorials

Page 10: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Problem driven education

Page 11: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Problem statement

$("#button").fadeIn("slow", function() { console.log("hello world"); } );

Page 12: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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 13: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Problem statement

Page 14: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Kinda solution

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 15: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Type: async result

> java.util.concurrent.Future<V>

> boolean isDone(); > V get() … > V get(long timeout, TimeUnit unit)

Page 16: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Type: async result

> java.util.concurrent.Future<V>

> boolean isDone(); > V get() … > V get(long timeout, TimeUnit unit)

Can we do

better?

Page 17: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Monads to the rescue

Page 18: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Monads to the rescue

Page 19: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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 20: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

It is known

Every cook can understand, compile and use monads…

V. Lenin (1923)

Page 21: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every
Page 22: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Monads: intuition

> wrapping things

> chaining functions on those things

> monad is a type

Page 23: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every
Page 24: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Wrapping: return / pure

> Take instance of “a”, return: “m a”

> Constructor / Factory method

Page 25: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Pure in Java

public interface Monad<V> { Monad<V> pure(V value); }

Page 26: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Chaining: bind / (>>=)

> take:

> monad: “m a”

> function: “a => m b”

> return: monad “m b”

Page 27: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Bind in Java

public interface Monad<V> { Monad<V> pure(V v); <R> Monad<R> bind(Function<V, Monad<R>> f); }

Page 28: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Hacking time

> Promise<V> - result of async computation

> Kinda like Future<V>

> supports chaining functions: bind

Page 29: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Imagined Promise<V>

> Future operations > p.invokeWithException(Throwable t); > p.invoke(V v); > p.onRedeem(Action<Promise<V>> callback);

Page 30: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Promise<V>: pure

public static <V> Promise<V> pure (final V v) { Promise<V> p = new Promise<>(); p.invoke(v); return p; }

Page 31: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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 32: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Promise<V>: get

public V get() throws InterruptedException, ExecutionException { taskLock.await(); if (exception != null) { throw new ExecutionException(exception); } return result; }

Page 33: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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 34: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Checkpoint

> Promise - represents async computation

> Values and exceptions handling

> Chaining of functions

Page 35: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Wait, is that it?

> Monad vs. Instance of monad

Page 36: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Typeclass? Higher functions?

> Common interface

> Generic functions over all monads

Page 37: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Greatness

> Common operations for Monads

> sequence, zip

> Limited under parametrised polymorphism in Java

Page 38: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Sequence

Monad<List<V>> sequence(Monad<V>... monads);

Page 39: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Some languages have it easier than others

> m >> n = m >>= \_ -> n

> f x a = … a

> Implicit get()

Page 40: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Monad in Java

public interface Monad<V> { Monad<V> pure(V v); <R> Monad<R> bind(Function<V, Monad<R> f); V get(); }

Page 41: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

> One does not simply call itself a monad!

Page 42: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every
Page 43: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Laws (don’t be scared)

> return a >>= f ≡ f a

> m >>= return ≡ m

> (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)

Page 44: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Left identity

> pure(v).bind(f) ≡ f.apply(v)

Page 45: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Right identity

> m.bind(m::pure) ≡ m

Page 46: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Associativity

> m.bind(f).bind(g) ≡ m.bind(

(v) -> f.apply(v).bind(g))

Page 47: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Some have it easy

> Referential transparency

> Partial application

> ≡ is easy

Page 48: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Mortal platforms

> No referential transparency

> f.apply(v) != f.apply(v)

> equals() + hashcode()

Page 49: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Defining ≡ for Java

> Side effects are similar

> m.get() observes the same values

> values or exceptions

Page 50: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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 51: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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 52: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Quality software

> java.util.concurrent.CompletableFuture

> thenApply(Function / Consumer / etc)

> thenApplyAsync(Function / etc)

> Async => FJP.common()

Page 53: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every
Page 54: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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 55: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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 56: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

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 57: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every
Page 58: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every
Page 59: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Free STUFF

BOOTH #8

Page 60: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Free STUFF

http://bit.ly/tshirt-oleg

Page 61: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

[email protected] @shelajev github.com/shelajev/promises

Contact me

Page 62: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Minority report

> Alternative definition of Monads:

> fmap :: (a -> b) -> f a -> f b

> join :: m (m a) -> m a

Page 63: with Java 8 › jfokus15 › preso › Monads.pdf · > a monad in X is just a monoid in the category of ... endofunctors and unit set by the identity endofunctor. It is known Every

Exercises

> Implement (>>=) in terms of fmap and join.

> Now implement join and fmap in terms of (>>=) and return.


Recommended