@cesarTronLozai
What the ƒ is a Monad?
artist: Heni Sandoval
@cesarTronLozai
What the ƒ is a Monad?
artist: Heni Sandoval
@cesarTronLozai
Why this talk?
@cesarTronLozai
Why this talk?
@cesarTronLozai
Why this talk?
@cesarTronLozai
Why this talk?
@cesarTronLozai
Disclaimer
@cesarTronLozai
Why should you care?
• Functional Programming is the new black
• Scala, C#, Clojure, Haskell, “JavaScript”, Java 8 etc..
• Java community is lagging behind
• C# introduced Lambdas in 2007 (C# 3.0)…
• Little knowledge of theoretical foundations
• Functor, applicative, monad etc..
• Perhaps Java is heading more towards FP, better be prepared
@cesarTronLozai
Why should you care?
• Write “better” code
• Strong typing -> robust and expressive code
• Readability -> small functions that do less
• Immutability -> easier to reason the flow
• Reusable functions -> leaner code
• Simple when familiar
@cesarTronLozai
What I want to do today?
• There are a lot of very good practical talks about FP
• A Pragmatist’s Guide to Functional Geekery by Michał Płachta
• g ∘ f patterns by Mario Fusco
• I want
• To give you insight into the underlying theory
• Simplify the theory so you remember
• To interest you to go and look for more
• Help you understand future readings about Monad
@cesarTronLozai
Notations - Function Types
parseInt :: String -> int
public int parseInt(String i)
•f :: A -> B
A B
f
f
f Add :: int -> int -> int
public int add(int x, int y)
@cesarTronLozai
Notations - Function Composition
f :: A -> B
g :: B -> C
g o f :: A -> C
o :: (A->B)->(B->C)->(A->C)
Function composition
A B C
f
f
g
g
g o f
g o f
@cesarTronLozai
Higher Order Function
//first-order function
public int timesTwo(int i){
return i * 2;
}
//higher-order function
public Function<Integer, Integer> multiplyBy(int n){
return x -> x * n;
}
//higher-order function
public Function<Integer, Integer> twice(Function<Integer, Integer> f){
return i -> f.andThen(f).apply(i);
}
@cesarTronLozai
Pure Functional
Programming
@cesarTronLozai
Pure Functional Programming
• Programs composed of “pure” functions =>
• No side effects
• Can be “memoized” i.e. always return the same (i.e. it’s a map)
• Side effects are1
Modifying a variable
Modifying a data structure in place
Setting a field on an object
Throwing an exception or halting with an error
Printing to the console or reading user input
Reading from or writing to a file
Drawing on the screen
• Declarative style instead of imperative -> What not How1Chapter 1 of “Functional Programming”, Paul Chiusano & Runar Bjarnason
@cesarTronLozai
Pure Functional Programming
@cesarTronLozai
Pure Functional Programming
•exceptions = partial function
A B
f
f
f
The partial
function is a
lie
@cesarTronLozai
Pure Functional Programming
• How to make a useful program?
• => Minimise and control side effects
Side
effects
Pure
functions
Input Output
Database
@cesarTronLozai
Functor
@cesarTronLozai
Functor
Optional<Integer> intOption = Optional.of(42);
Function<Integer, String> toStr = i -> i.toString();
Optional<String> strOption = intOption.map(toStr);
CompletableFuture<Integer> intFuture = completedFuture(42)
CompletableFuture<String> strFuture = intFuture.thenApply(f)
List<Integer> numbers = List.of(1, 2, 3);
List<String> strings =
numbers.stream().map(toStr).collect(Collectors.toList());
@cesarTronLozai
Functor
• The function that creates the lifted function is called map
map (g)
F :: A -> F[A]
g :: A -> B
map :: (A -> B) -> F[A] -> F[B]
map(g) :: F[A] -> F[B]
g
F
F
@cesarTronLozai
Functor
g
1 2 {}
1 2 {}
Some< >
map (g)
Empty<>
map (g)
map (g)
Optional< >
Some< > Empty<>
@cesarTronLozai
Functor
• Functor Summary
• Container for types
• map “lifts” functions
• Lifted functions change the content of the box, not the box
• Structure is unchanged
@cesarTronLozai
Functor
Definition
functor ≈ map
@cesarTronLozai
Monad!
@cesarTronLozai
Monad
• From Bartosz Milewski’s blog post on Monad
• Can you guess what this object is?
• Fixing CO2 scrubbers on board of Apollo 13
• Wart treatment
• Fixing Apple’s iPhone 4 dropped call issue
• Making a prom dress
• Building a suspension bridge
@cesarTronLozai
Use case
@cesarTronLozai
Use case
input="126,3", output:126/3 = 42
public (String, String) split(String s){
return s.split(",")
}
public (double, double) parse((String, String) p){
return (parseDouble(p._1), parseDouble(p._2))
}
public double divide ((double, double) numbers){
return numbers._1 / numbers._2
}
@cesarTronLozai
Use case
split
parse
divide
@cesarTronLozai
split
parse
divide
divide ∘ parse ∘ split
Use case
@cesarTronLozai
• Exceptions -> Partial functions
• We modify functions to return “embellished” results
f f
Use case
Wrapper
@cesarTronLozai
Optional<T> Either<L, R>
Optional.of(“OK”)
Optional.empty()
Either.left(new Exception(“…”))
Either.right(“OK”)
Exception handling
Use case
@cesarTronLozai
Asynchronous process
public String sayHello(){
return "Hello";
}
Use case
public CompletableFuture<String> sayHello(){
return CompletableFuture.supplyAsync(() -> {
return "Hello";
})
}
@cesarTronLozai
Logging
public Pair<Integer, String> getMagicNumber(){
final StringBuilder builder = new StringBuilder();
builder.append("About to compute the numbern");
final int magicNumber = 126/3;
builder.append(“Finished computing the numbern");
return Pair.of(magicNumber, builder.toString());
}
Use case
@cesarTronLozai
Environment
public Function<Properties, String> buildUrl(){
return properties -> {
final String host = properties.getProperty("host");
final String port = properties.getProperty("port");
return String.format("http://%s:%s", host, port);
}
}
Use case
@cesarTronLozai
public Optional<(String,String)> split(String s)
public Optional<(double, double)> parse((String, String) p)
public Optional<double> divide ((double, double) numbers)
Let’s try with Optional
Use case
@cesarTronLozai
Use case
public Optional<Double> myProgram(String s){
final Optional<(String,String)> split = split(s);
if(split.isPresent()){
final Optional<(double, double)> parse = parse(split.get());
if(parse.isPresent()){
final Optional<Double> result = divide(parse.get());
if(result.isPresent()){
return result.get();
}
}
}
return Optional.empty();
}
@cesarTronLozai
Use case
@cesarTronLozai
split
parse
divide
Use case
@cesarTronLozai
split
parse
divide
????
Use case
@cesarTronLozai
f :: A -> M[B]
g :: B -> M[C]
g >=> f :: A -> M[C]
• How can we compose wrapped result types??
g
f
g >=> f
Use case
@cesarTronLozai
f :: A -> M[B]
g :: B -> M[C]
map(g) o f :: A -> M[M[C]]
g >=> f :: A -> M[C]
Can we use a Functor??
map (g)
f
map (g) o f
We need something that can do M[M[T]] -> M[T]
g
Use case
@cesarTronLozai
Monad
map g
f
flatten
flatten
flatten o map (g) o f
f :: A -> M[B]
g :: B -> M[C]
g >=> f :: A -> M[C]
g >=> f = flatten o map (g) o f
g
@cesarTronLozai
Functor
Definition
Monad ≈ Functor + flatten
@cesarTronLozai
Monad
flatmap (g) = flatten o map (g)
M :: A -> M[A]
f :: A -> M[B]
map ::(A -> B) -> M[A] -> M[B]
flatmap ::(A -> M[B]) -> M[A] -> M[B]
g >=> f = x -> flatmap(g)(f(x))
flatten
g
map g
@cesarTronLozai
Monad
g >=> f = x -> flatmap(g)(f(x))
g >=> f = flatmap g f
>=> ≈ flatmap
add : int -> int -> int
a + b = add a b
+ ≈ add
@cesarTronLozai
Monad
split
parse
divide
divide >=> parse >=> split
@cesarTronLozai
Functor
Definition
monad ≈ flatmap
@cesarTronLozai
Monad
• Exception handling
• Optional
• Either
• Asynchronous process
• CompletableFuture
• Logging
• Environment
@cesarTronLozai
Monad
public static <T> CompletableFuture<T> completedFuture(T value)
public static <T> Optional<T> of(T value)
public static <T> Stream<T> of(T e)
flatmap ::(A -> M[B]) -> M[A] -> M[B]
pure :: A -> M[A]
@cesarTronLozai
Monad
• Definition
• Functor + flatten
• flatmap
• Advantages
• Manage and control side effects
• Program with side effect as if they were not here
• Monad makes partial functions total
• Composes functions with side effects with flatmap
@cesarTronLozai
Monad
public Optional<Double> myProgram(String s){
final Optional<(String,String)> split = split(s);
if(split.isPresent()){
final Optional<(double, double)> parse = parse(split.get());
if(parse.isPresent()){
final Optional<Double> result = divide(parse.get());
if(result.isPresent()){
return result.get();
}
}
}
return Optional.empty();
}
@cesarTronLozai
Monad
public Optional<Double> myProgram(String s) {
return split(s)
.flatMap(split -> parse(split))
.flatMap(parse -> divide(parse));
}
@cesarTronLozai
Monad
def split(s: String): Option[(String, String)] = ???
def parse(p: (String, String)): Option[(Double, Double)] = ???
def divide(n: (Double, Double)): Option[Double] = ???
def myProgram(s: String): Option[Double] = {
for {
split <- split(s)
parse <- parse(split)
divide <- divide(parse)
} yield divide
}
@cesarTronLozai
Monad
Unmanaged SE Managed SE
Composable
Non composable
Monad
@cesarTronLozai
Key takeaways
4. Monad allows composition of wrapper data types
g >=> f
3. Pick Monads for Embellished/wrapper types to manage side effects
1. Functor ≈ map
2. Monad ≈ flatmap
@cesarTronLozai
Before you go
• Be pragmatic
• Keep an eye out
@cesarTronLozai
What the ƒ is a monad?
@cesarTronLozai
Sources
• Bartosz Milewski, “Category Theory for programmers”
• Video lectures
• Blog posts
• “Functional Programming” by Paul Chiusano & Runar Bjarnason
(ISBN 9781617290657)
• Pattern matching with Brian Goetz - 2017 JVMLS
• The art of Simplicity by Venkat Subramaniam (vJUG24 Key note)
@cesarTronLozai
Thank you
• Thank you @BartoszMilewski
• Thank you @GeorgianaElenaL
• Thank you @JulienTruffaut
@cesarTronLozai
Questions
?
@cesarTronLozai

What the f is a monad?

Editor's Notes

  • #4  Java dev, got interested in Java 8 lambda, reading about Optional and Future, stumbled upon Monad article -> show Jacky -> Decided to learn about FP, keep seeing this Monad guy everywhere, got interested in Category Theory
  • #5 then suddenly
  • #6 Had an epiphany
  • #7 Now I’m trying to convince you that Monad is a simple and useful concept, without having to through the maths
  • #8 Famous ancient mathematician, Even though I have a lot of respect for his work, I have to disagree with Boromir -> Goal is to make you understand the main idea, without scaring you away
  • #9 “Making a comeback”, mention Reactive programming -> perhaps has always been here, we just forgot about it Lisp 1958 Java 8 March 2014 Talks at Scala Exchange
  • #14 HOF: takes a function and/or returns a function Hybrid approach with interface
  • #16 FP is a way of life, philosophy about writing code 1Chapter 1 of “Functional Programming”, Paul Chiusano & Runar Bjarnason mention immutability Talking about exception ->
  • #17 obviously it’s .Net, would never happen in Java
  • #18 Function lies about the type, it does not return a B Not predictable, not reproducible
  • #19 like with unit testing, push dependencies at the ends
  • #20 No time to detail all benefits, quick review parallelisation -> no race condition
  • #21 Before we talk about monad we need to look at Functor
  • #22 Map is a higher order function
  • #23 Functor must do two things: “Lift” a Type A into another Type B Lift functions of A to Functions of B Spend time here, make sure you give examples e.g. “put int in a box” Can be in a class instead of static method We replace the content of the box by the result of the function
  • #24 Examples of monad Optional and Monad Only one implementation Structure is not changed -> List size does not change
  • #25 Structure is not changed! -> map a list of 3 elements you still have 3 elements, similar with Optional
  • #26 Mention Boromir, he is a bit upset
  • #27 Park Functor in your head, we will use it later
  • #28 The problem with Monad is that it is usually described using example that are very different from each other This need not be the case We can understand what is the essence of a Monad Joke about example
  • #30 Almost java code
  • #31 What could go wrong?? Exception, etc…
  • #32 What could go wrong?? Exception, etc…
  • #33 Partial function
  • #39 What a beautiful piece of code
  • #40 Honest java programmer Greedy Functional programmer
  • #42 Key problem here, how do we compose embellished types
  • #43 The Kleisli arrow, bind operator
  • #44 ask Audience, “what does a functor have?” Double Tupperware show it’s same container
  • #45 found the fish, this is the definition of monad
  • #47 another definition of monad Can be functor with flatten, or just flatmap of course flatmap implies functor flatmap () We can combine embellished function with flatmap
  • #48 Infixed notation In java >=> = flatmap
  • #49 Could be written with flatmap
  • #51 All monads, all have a flat map of sort
  • #52 All monads, all have a flat map of sort
  • #53 All side effects can be translated into a pure function with a monad
  • #56 if you want to chain operation that don’t fail -> map operation that may fail (with Optional) -> use flatmap What I said is not fair to FP programers, they are also hypocrites
  • #57 Functional programmer are greedy Haskell is the best imperative language
  • #58 re-iterate
  • #65 Actual implementation in Java Hacking empty
  • #66 Show laziness, mapper not called if empty -> FP programers are also hypocrite
  • #67 Actual implementation in Java Hacking empty
  • #68 Hybrid approach with interface
  • #69 Pattern Matching with Brian Goetz @BrianGoetz JVM Language Summit 2017 Pattern match: applicativity test + destructuring bind
  • #70 Throughout history … Mother of all theories, very abstract Functional Programming takes a lot of concept from Category Theory Elements of this talk like Functors and Mondas are formally defined in Category Theory
  • #71 “Category Theory” -> Most complex concept, smallest slide Mother of all theories, very abstract Functional Programming takes a lot of concept from Category Theory Elements of this talk like Functors and Mondas are formally defined in Category Theory
  • #73 Pattern Matching with Brian Goetz @BrianGoetz JVM Language Summit 2017 Talk about alternative of map using java polymorphism
  • #74 This is pattern matching
  • #75 mention that any ADT is a functor
  • #76 Functor is a container, map will unpack, modify, repack