SlideShare a Scribd company logo
1 of 103
Download to read offline
[error] Exception encountered
[error] java.lang.StackOverflowError
WHY THE FREE MONAD ISN’T FREE
“Let’s just trampoline it and
add the Free Monad”
@kelleyrobinson
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
“Let’s just trampoline it and
add the Free Monad”
Why The Free
Monad Isn’t Free
Kelley Robinson
Data & Infrastructure Engineer
Sharethrough
@kelleyrobinson
WHY THE FREE MONAD ISN’T FREE
- Monoids, Functors & Monads
- How to be “Free”
- Why & Why Not “Free”
- Alternatives
- Real World Applications
$
@kelleyrobinson
WHY THE FREE MONAD ISN’T FREE
github.com/robinske/monad-examples
WHY THE FREE MONAD ISN’T FREE
https://twitter.com/rickasaurus/status/705134684427128833
WHY THE FREE MONAD ISN’T FREE
Monoids
@kelleyrobinson
@kelleyrobinson
trait Monoid[A] {


def append(a: A, b: A): A


def identity: A

}
WHY THE FREE MONAD ISN'T FREE
Monoids
Image credit: deluxebattery.com
WHY THE FREE MONAD ISN'T FREE
Properties
Identity: "no-op" value
Associativity:
grouping doesn't matter
@kelleyrobinson
@kelleyrobinson
object StringConcat extends Monoid[String] {



def append(a: String, b: String): String = a + b



def identity: String = ""



}
@kelleyrobinson
object IntegerAddition extends Monoid[Int] {



def append(a: Int, b: Int): Int = a + b



def identity: Int = 0



}
@kelleyrobinson
object IntegerMultiplication extends Monoid[Int] {



def append(a: Int, b: Int): Int = a * b



def identity: Int = 1



}
@kelleyrobinson
object FunctionComposition /* extends Monoid[_=>_] */ {



def append[A, B, C](f1: A => B, f2: B => C): A => C =
(a: A) => f2(f1(a))



def identity[A]: A => A = (a: A) => a


}
@kelleyrobinson
object FunctionComposition /* extends Monoid[_=>_] */ {



def append[A, B, C](f1: A => B, f2: B => C): A => C =
(a: A) => f2(f1(a))



def identity[A]: A => A = (a: A) => a


}
WHY THE FREE MONAD ISN’T FREE
Functors
@kelleyrobinson
@kelleyrobinson
trait Functor[F[_]] {



def map[A, B](a: F[A])(fn: A => B): F[B]



}
WHY THE FREE MONAD ISN'T FREE
@kelleyrobinson
Properties
Identity: "no-op" value
Composition:
grouping doesn't matter
@kelleyrobinson
sealed trait Option[+A]

case class Some[A](a: A) extends Option[A]

case object None extends Option[Nothing]
object OptionFunctor extends Functor[Option] {



def map[A, B](a: Option[A])(fn: A => B): Option[B] =

a match {

case Some(something) => Some(fn(something))

case None => None

}

}
@kelleyrobinson
it("should follow the identity law") {

def identity[A](a: A): A = a

assert(map(Some("foo"))(identity) == Some("foo"))

}
@kelleyrobinson
it("should follow the composition law") {
val f: String => String = s => s + "a"

val g: String => String = s => s + "l"
val h: String => String = s => s + "a"
assert(
map(Some("sc"))(f andThen g andThen h) ==
map(map(map(Some("sc"))(f))(g))(h) ==
"scala"
)
}
Functors are Endofunctors**
**in Scala
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
WHY THE FREE MONAD ISN’T FREE
Monads
@kelleyrobinson
"The term monad is a bit
vacuous if you are not a
mathematician. An alternative
term is computation builder."
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson http://stackoverflow.com/questions/44965/what-is-a-monad
@kelleyrobinson
trait Monad[M[_]] {


def pure[A](a: A): M[A]

def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]

}
@kelleyrobinson
sealed trait Option[+A]

case class Some[A](a: A) extends Option[A]

case object None extends Option[Nothing]



object OptionMonad extends Monad[Option] {



def pure[A](a: A): Option[A] = Some(a)



def flatMap[A, B](a: Option[A])(fn: A => Option[B]): Option[B] =

a match {

case Some(something) => fn(something)

case None => None

}

}
@kelleyrobinson
trait Monad[M[_]] {


def pure[A](a: A): M[A]

def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]

}
@kelleyrobinson
trait Monad[M[_]] {

def pure[A](a: A): M[A]

def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]



def map[A, B](a: M[A])(fn: A => B): M[B] = {

flatMap(a){ b: A => pure(fn(b)) }

}


}
@kelleyrobinson
trait Monad[M[_]] {
def pure[A](a: A): M[A]

def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]



def map[A, B](a: M[A])(fn: A => B): M[B] = {

flatMap(a){ b: A => pure(fn(b)) }

}

}
@kelleyrobinson
trait Monad[M[_]] {

def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]

def append[A, B, C]
(f1: A => M[B], f2: B => M[C]): A => M[C] = {
a: A =>

val bs: M[B] = f1(a)

val cs: M[C] = flatMap(bs) { b: B =>
f2(b)
}

cs

}


}
@kelleyrobinson
trait Monad[M[_]] {

def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]

def append[A, B, C]
(f1: A => M[B], f2: B => M[C]): A => M[C] = {
a: A =>

val bs: M[B] = f1(a)

val cs: M[C] = flatMap(bs) { b: B =>
f2(b)
}

cs

}


}
WHY THE FREE MONAD ISN'T FREE
Properties
Identity: "no-op" value
Composition:
grouping doesn't matter
@kelleyrobinson
WHY THE FREE MONAD ISN'T FREE
Compose functions
for values in a
context
Think: Lists, Options, Futures
@kelleyrobinson
trait Monad[M[_]]
extends Functor[M]
/* with Monoid[_=>M[_]] */ {


def pure[A](a: A): M[A]

def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]



def map[A, B](a: M[A])(fn: A => B): M[B]

def append[A, B, C](f1: A => M[B], f2: B => M[C]): A => M[C]

def identity[A]: A => M[A]

}
@kelleyrobinson
trait Monad[M[_]]
extends Functor[M]
/* with Monoid[ _ => M[_] ] */ {


def pure[A](a: A): M[A]

def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]



def map[A, B](a: M[A])(fn: A => B): M[B]

def append[A, B, C](f1: A => M[B], f2: B => M[C]): A => M[C]

def identity[A]: A => M[A]

}
@kelleyrobinson
trait Monad[M[_]]
extends Functor[M]
/* with Monoid[ _ => M[_] ] */ {


def pure[A](a: A): M[A]

def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]



def map[A, B](a: M[A])(fn: A => B): M[B]

def append[A, B, C](f1: A => M[B], f2: B => M[C]): A => M[C]

def identity[A]: A => M[A]

}
@kelleyrobinson
object FunctionComposition /* extends Monoid[_ => _] */{



...
}
trait Monad[M[_]] /* extends Monoid[_ => M[_]] */{


...
}
WHY THE FREE MONAD ISN’T FREE
- Monoids, Functors & Monads
- How to be “Free”
- Why & Why Not “Free”
- Alternatives
- Real World Applications
$
@kelleyrobinson
WHY THE FREE MONAD ISN'T FREE
The word "free" is
used in the sense of
"unrestricted" rather
than "zero-cost"
$
@kelleyrobinson
WHY THE FREE MONAD ISN'T FREE
"Freedom not beer"
https://en.wikipedia.org/wiki/Gratis_versus_libre#/media/File:Galuel_RMS_-_free_as_free_speech,_not_as_free_beer.png
WHY THE FREE MONAD ISN’T FREE
Free Monoids
@kelleyrobinson
@kelleyrobinson
trait Monoid[A] {


def append(a: A, b: A): A

def identity: A

}
WHY THE FREE MONAD ISN’T FREE
Free Monoids
• Free from interpretation
• No lost input data when
appending
@kelleyrobinson
image credit: http://celestemorris.com
@kelleyrobinson
// I'm free!
class ListConcat[A] extends Monoid[List[A]] {

def append(a: List[A], b: List[A]): List[A] =
a ++ b

def identity: List[A] = List.empty[A]

}
@kelleyrobinson
// I'm not free :(
object IntegerAddition extends Monoid[Int] {



def append(a: Int, b: Int): Int = a + b



def identity: Int = 0



}
WHY THE FREE MONAD ISN’T FREE
Free Monads
@kelleyrobinson
Don't lose any data!
(that means no evaluating functions)
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
@kelleyrobinson
def notFreeAppend[A, B, C]
(f1: A => M[B], f2: B => M[C]): A => M[C] = {
a: A =>

// evaluate f1
val bs: M[B] = f1(a)
// evaluate f2

val cs: M[C] = flatMap(bs) { b: B => f2(b) }

cs
}
@kelleyrobinson
sealed trait Free[F[_], A] { self =>



}

@kelleyrobinson
sealed trait Free[F[_], A] { self =>

}



case class Return[F[_], A](given: A) extends Free[F, A]
@kelleyrobinson
sealed trait Free[F[_], A] { self =>



}



case class Return[F[_], A](given: A) extends Free[F, A]
case class Suspend[F[_], A](fn: F[A]) extends Free[F, A]

@kelleyrobinson
sealed trait Free[F[_], A] { self =>



}



case class Return[F[_], A](given: A) extends Free[F, A]
case class Suspend[F[_], A](fn: F[A]) extends Free[F, A]

case class FlatMap[F[_], A, B]
(free: Free[F, A], fn: A => Free[F, B])
extends Free[F, B]
@kelleyrobinson
sealed trait Free[F[_], A] { self =>
def flatMap ...
def pure ...
def map ...
}



case class Return[F[_], A](given: A) extends Free[F, A]
case class Suspend[F[_], A](fn: F[A]) extends Free[F, A]

case class FlatMap[F[_], A, B]
(free: Free[F, A], fn: A => Free[F, B])
extends Free[F, B]
@kelleyrobinson
sealed trait Todo[A]

case class NewTask[A](task: A) extends Todo[A]

case class CompleteTask[A](task: A) extends Todo[A]

case class GetTasks[A](default: A) extends Todo[A]
def newTask[A](task: A): Free[Todo, A] =
Suspend(NewTask(task))

def completeTask[A](task: A): Free[Todo, A] =
Suspend(CompleteTask(task))

def getTasks[A](default: A): Free[Todo, A] =
Suspend(GetTasks(default))
@kelleyrobinson
val todos: Free[Todo, Map[String, Boolean]] =

for {

_ <- newTask("Go to scala days")

_ <- newTask("Write a novel")

_ <- newTask("Meet Tina Fey")

_ <- completeTask("Go to scala days")

tsks <- getTasks(Map.empty)

} yield tsks
@kelleyrobinson
val todosExpanded: Free[Todo, Map[String, Boolean]] =

FlatMap(

Suspend(NewTask("Go to scala days")), (a: String) =>

FlatMap(

Suspend(NewTask("Write a novel")), (b: String) =>

FlatMap(

Suspend(NewTask("Meet Tina Fey")), (c: String) =>

FlatMap(

Suspend(CompleteTask("Go to scala days")),
(d: String) =>
Suspend(GetTasks(default = Map.empty))

)

)

)

)
WHY THE FREE MONAD ISN’T FREE
- Monoids, Functors & Monads
- How to be “Free”
- Why & Why Not “Free”
- Alternatives
- Real World Applications
$
@kelleyrobinson
WHY THE FREE MONAD ISN'T FREE
What's the point?
• Defer side effects
• Multiple interpreters
• Stack safety
@kelleyrobinson
@kelleyrobinson


(1 to 1000).flatMap { i =>

doSomething(i).flatMap { j =>

doSomethingElse(j).flatMap { k =>

doAnotherThing(k).map { l =>

...
WHY THE FREE MONAD ISN’T FREE
“Let’s just trampoline it and
add the Free Monad”
@kelleyrobinson
WHY THE FREE MONAD ISN’T FREE
Trampolining
Express it in a loop
@kelleyrobinson
WHY THE FREE MONAD ISN’T FREE
The Free Monad
uses heap instead of
using stack.
@kelleyrobinson
@kelleyrobinson
val todosExpanded: Free[Todo, Map[String, Boolean]] =

FlatMap(

Suspend(NewTask("Go to scala days")), (a: String) =>

FlatMap(

Suspend(NewTask("Write a novel")), (b: String) =>

FlatMap(

Suspend(NewTask("Meet Tina Fey")), (c: String) =>

FlatMap(

Suspend(CompleteTask("Go to scala days")),
(d: String) =>
Suspend(GetTasks(default = Map.empty))

)

)

)

)
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
Evaluating
Use a loop
@kelleyrobinson
def runFree[F[_], G[_], A]
(f: Free[F, A])
(transform: FunctorTransformer[F, G])
(implicit G: Monad[G]): G[A]
@kelleyrobinson
def runFree[F[_], G[_], A]
(f: Free[F, A])
(transform: FunctorTransformer[F, G])
(implicit G: Monad[G]): G[A]
Turn F into G -
AKA "Natural Transformation"Input
`G` must be a monad so we can flatMap
@kelleyrobinson
// or 'NaturalTransformation'

trait FunctorTransformer[F[_], G[_]] {

def apply[A](f: F[A]): G[A]

}

// Common symbolic operator
type ~>[F[_], G[_]] = FunctorTransformer[F, G]
@kelleyrobinson
/* Function body */
@annotation.tailrec

def tailThis(free: Free[F, A]): Free[F, A] = free match {

case FlatMap(FlatMap(fr, fn1), fn2) => ...
case FlatMap(Return(a), fn) => ...
case _ => ...

}



tailThis(f) match {

case Return(a) => ...

case Suspend(fa) => ...
case FlatMap(Suspend(fa), fn) => ...
case _ => ...

}
https://github.com/robinske/monad-examples
@kelleyrobinson
tailThis(f) match {

case Return(a) => ...

case Suspend(fa) => transform(fa)
case FlatMap(Suspend(fa), fn) =>
monad.flatMap(transform(fa))(a =>
runFree(fn(a))(transform))
case _ => ...

}
https://github.com/robinske/monad-examples
@kelleyrobinson
def runLoop[F[_], G[_], A](...): G[A] = {

var eval: Free[F, A] = f



while (true) {

eval match {

case Return(a) => ...

case Suspend(fa) => ...

case FlatMap(Suspend(fa), fn) => ...

case FlatMap(FlatMap(given, fn1), fn2) => ...

case FlatMap(Return(s), fn) => ...

}

}



throw new AssertionError("Unreachable")

}
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
Evaluating
Applies transformation on
`Suspend`
Trampolining for stack safety
@kelleyrobinson
// or 'NaturalTransformation'

trait FunctorTransformer[F[_], G[_]] {

def apply[A](f: F[A]): G[A]

}

// Common symbolic operator
type ~>[F[_], G[_]] = FunctorTransformer[F, G]
@kelleyrobinson
type Id[A] = A
case class TestEvaluator(var model: Map[String, Boolean])
extends FunctorTransformer[Todo, Id] {



def apply[A](a: Todo[A]): Id[A]
}
@kelleyrobinson
a match {
case NewTask(task) =>

model = model + (task.toString -> false)

task

case CompleteTask(task) =>

model = model + (task.toString -> true)

task

case GetTasks(default) =>

model.asInstanceOf[A]
}
@kelleyrobinson
it("should evaluate todos") {

val result =
runFree(todos)(TestEvaluator(Map.empty))

val expected: Map[String, Boolean] =

Map(

"Go to scala days" -> true,

"Write a novel" -> false,

"Meet Tina Fey" -> false

)

result shouldBe expected

}
@kelleyrobinson
case object ActionTestEvaluator
extends FunctorTransformer[Todo, Id] {


var actions: List[Todo[String]] = List.empty

def apply[A](a: Todo[A]): Id[A]
}
@kelleyrobinson
a match {
case NewTask(task) =>

actions = actions :+ NewTask(task.toString)

task

case CompleteTask(task) =>

actions = actions :+ CompleteTask(task.toString)

task

case GetTasks(default) =>

actions = actions :+ GetTasks("")

default
}
@kelleyrobinson
it("should evaluate todos actions in order") {

runFree(todos)(ActionTestEvaluator)



val expected: List[Todo[String]] =

List(

NewTask("Go to scala days"),

NewTask("Write a novel"),
NewTask("Meet Tina Fey"),

CompleteTask("Go to scala days"),
GetTasks("")

)


ActionTestEvaluator.actions shouldBe expected

}
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
Defining multiple interpreters allows
you to test side-effecting code without
using testing mocks.
@kelleyrobinson
// Production Interpreter
def apply[A](a: Todo[A]): Option[A] = {

a match {

case NewTask(task) =>

/**
* Some if DB write succeeds
* None if DB write fails
*
*/

case CompleteTask(task) => ...

case GetTasks(default) => ...

}

}
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
Justifications
• Defer side effects
• Multiple interpreters
• Stack safety
WHY THE FREE MONAD ISN'T FREE
#BlueSkyScala
The path to learning is broken
@kelleyrobinson
Credit: Jessica Kerr
WHY THE FREE MONAD ISN'T FREE
Freedom isn't free
Reasons to avoid the Free Monad
• Boilerplate
• Learning curve
• Alternatives
@kelleyrobinson
Credit: Jessica Kerr
WHY THE FREE MONAD ISN’T FREE
- Monoids, Functors & Monads
- How to be “Free”
- Why & Why Not “Free”
- Alternatives
- Real World Applications
$
@kelleyrobinson
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
Know your domain
WHY THE FREE MONAD ISN'T FREE
Functional Spectrum
Where does your team fall?
Java Haskell
WHY THE FREE MONAD ISN'T FREE
Functional Spectrum
Where does your team fall?
Java Haskell
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
Alternatives for
maintaining stack
safety
@kelleyrobinson
final override def map[B, That](f: A => B)
(implicit bf: CanBuildFrom[List[A], B, That]): That = {

if (bf eq List.ReusableCBF) {

if (this eq Nil) Nil.asInstanceOf[That] else {

val h = new ::[B](f(head), Nil)

var t: ::[B] = h

var rest = tail

while (rest ne Nil) {

val nx = new ::(f(rest.head), Nil)

t.tl = nx

t = nx

rest = rest.tail

}

h.asInstanceOf[That]

}

}

else super.map(f)

}
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
Alternatives for
managing side
effects
@kelleyrobinson
import java.sql.ResultSet



case class Person(name: String, age: Int)



def getPerson(rs: ResultSet): Person = {

val name = rs.getString(1)

val age = rs.getInt(2)

Person(name, age)

}
@kelleyrobinson
def handleFailure[A](f: => A): ActionResult / A = {

Try(f) match {

case Success(res) => res.right

case Failure(e) =>
InternalServerError(reason = e.getMessage).left

}

}


handleFailure(getPerson(rs))
WHY THE FREE MONAD ISN’T FREE
- Monoids, Functors & Monads
- How to be “Free”
- Why & Why Not “Free”
- Alternatives
- Real World Applications
$
@kelleyrobinson
WHY THE FREE MONAD ISN'T FREE
Scalaz
Scalaz is a Scala library for functional programming.
http://scalaz.github.io/scalaz/
Cats
Lightweight, modular, and extensible library for
functional programming.
http://typelevel.org/cats/
@kelleyrobinson
http://www.slideshare.net/jamesskillsmatter/real-world-scalaz
WHY THE FREE MONAD ISN'T FREE
Examples
• Doobie
• scalaz.concurrent.Task
@kelleyrobinson
https://github.com/tpolecat/doobie
@kelleyrobinson
import scalaz.concurrent.Task
def apply(conf: Config, messages: List[SQSMessage]): Unit = {

val tasks = messages.map(m => Task {

processSQSMessage(conf, m)

})



Task.gatherUnordered(tasks).attemptRun match {

case -/(exp) => error(s"Unable to process message")

case _ => ()

}

}
@kelleyrobinson
// yikes
object Task {

implicit val taskInstance:
Nondeterminism[Task] with Catchable[Task]
with MonadError[({type λ[α,β] =
Task[β]})#λ,Throwable] = new
Nondeterminism[Task] with Catchable[Task]
with MonadError[({type λ[α,β] =
Task[β]})#λ,Throwable] { ... }
}
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
My experience...
...what happened?
WHY THE FREE MONAD ISN’T FREE
- Know your domain
- Use clean abstractions
- Share knowledge
$
@kelleyrobinson
Thank You!
@kelleyrobinson
hello@krobinson.me
WHY THE FREE MONAD ISN’T FREE
@kelleyrobinson
Acknowledgements & Resources
Special thanks to:
• Sharethrough
• Rúnar Bjarnason
• Rob Norris
• Eugene Yokota
• Jessica Kerr
• David Hoyt
• Danielle Sucher
• Charles Ruhland
Resources for learning more about Free Monads:
• http://blog.higher-order.com/assets/trampolines.pdf
• http://eed3si9n.com/learning-scalaz/
• https://stackoverflow.com/questions/44965/what-is-a-monad
• https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/
• http://hseeberger.github.io/blog/2010/11/25/introduction-to-category-theory-in-scala/
• https://en.wikipedia.org/wiki/Free_object
• https://softwaremill.com/free-monads/
• https://github.com/davidhoyt/kool-aid/
• https://www.youtube.com/watch?v=T4956GI-6Lw
Other links and resources:
• https://skillsmatter.com/skillscasts/6483-keynote-scaling-intelligence-moving-ideas-forward
• https://stackoverflow.com/questions/7213676/forall-in-scala but that boilerplate

More Related Content

What's hot

Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)Scott Wlaschin
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programmingScott Wlaschin
 
The Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldThe Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldPhilip Schwarz
 
Java Programming | Java Tutorial For Beginners | Java Training | Edureka
Java Programming | Java Tutorial For Beginners | Java Training | EdurekaJava Programming | Java Tutorial For Beginners | Java Training | Edureka
Java Programming | Java Tutorial For Beginners | Java Training | EdurekaEdureka!
 
An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test frameworkAbner Chih Yi Huang
 
Implementing the IO Monad in Scala
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in ScalaHermann Hueck
 
JVM JIT compilation overview by Vladimir Ivanov
JVM JIT compilation overview by Vladimir IvanovJVM JIT compilation overview by Vladimir Ivanov
JVM JIT compilation overview by Vladimir IvanovZeroTurnaround
 
Python Objects
Python ObjectsPython Objects
Python ObjectsQuintagroup
 
The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)Scott Wlaschin
 
Infix to postfix expression in ds
Infix to postfix expression in dsInfix to postfix expression in ds
Infix to postfix expression in dsRohini Mahajan
 
Collections - Lists, Sets
Collections - Lists, Sets Collections - Lists, Sets
Collections - Lists, Sets Hitesh-Java
 
Exception handling and function in python
Exception handling and function in pythonException handling and function in python
Exception handling and function in pythonTMARAGATHAM
 
Java packages
Java packagesJava packages
Java packagesRaja Sekhar
 
F# for C# Programmers
F# for C# ProgrammersF# for C# Programmers
F# for C# ProgrammersScott Wlaschin
 
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...Chris Richardson
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of CompositionScott Wlaschin
 
A Brief Intro to Scala
A Brief Intro to ScalaA Brief Intro to Scala
A Brief Intro to ScalaTim Underwood
 

What's hot (20)

Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programming
 
The Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldThe Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and Fold
 
Java Programming | Java Tutorial For Beginners | Java Training | Edureka
Java Programming | Java Tutorial For Beginners | Java Training | EdurekaJava Programming | Java Tutorial For Beginners | Java Training | Edureka
Java Programming | Java Tutorial For Beginners | Java Training | Edureka
 
An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test framework
 
Implementing the IO Monad in Scala
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in Scala
 
JVM JIT compilation overview by Vladimir Ivanov
JVM JIT compilation overview by Vladimir IvanovJVM JIT compilation overview by Vladimir Ivanov
JVM JIT compilation overview by Vladimir Ivanov
 
Python Objects
Python ObjectsPython Objects
Python Objects
 
The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)
 
Infix to postfix expression in ds
Infix to postfix expression in dsInfix to postfix expression in ds
Infix to postfix expression in ds
 
Collections - Lists, Sets
Collections - Lists, Sets Collections - Lists, Sets
Collections - Lists, Sets
 
Exception handling and function in python
Exception handling and function in pythonException handling and function in python
Exception handling and function in python
 
Java packages
Java packagesJava packages
Java packages
 
F# for C# Programmers
F# for C# ProgrammersF# for C# Programmers
F# for C# Programmers
 
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
 
This pointer
This pointerThis pointer
This pointer
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of Composition
 
A Brief Intro to Scala
A Brief Intro to ScalaA Brief Intro to Scala
A Brief Intro to Scala
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 

Similar to Why The Free Monad isn't Free

Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Philip Schwarz
 
Monad and Algebraic Design in Functional Programming
Monad and Algebraic Design in Functional ProgrammingMonad and Algebraic Design in Functional Programming
Monad and Algebraic Design in Functional ProgrammingNamuk Park
 
Oh, All the things you'll traverse
Oh, All the things you'll traverseOh, All the things you'll traverse
Oh, All the things you'll traverseLuka Jacobowitz
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free MonadsJohn De Goes
 
Algebraic Data Types and Origami Patterns
Algebraic Data Types and Origami PatternsAlgebraic Data Types and Origami Patterns
Algebraic Data Types and Origami PatternsVasil Remeniuk
 
Monads and friends demystified
Monads and friends demystifiedMonads and friends demystified
Monads and friends demystifiedAlessandro Lacava
 
Kotlin Introduction with Android applications
Kotlin Introduction with Android applicationsKotlin Introduction with Android applications
Kotlin Introduction with Android applicationsThao Huynh Quang
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monadskenbot
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final TaglessJohn De Goes
 
Kleisli composition, flatMap, join, map, unit - implementation and interrelation
Kleisli composition, flatMap, join, map, unit - implementation and interrelationKleisli composition, flatMap, join, map, unit - implementation and interrelation
Kleisli composition, flatMap, join, map, unit - implementation and interrelationPhilip Schwarz
 
All You Need is Fold
All You Need is FoldAll You Need is Fold
All You Need is FoldMike Harris
 
Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adtsHang Zhao
 
Scala best practices
Scala best practicesScala best practices
Scala best practicesAlexander Zaidel
 
Fp in scala part 1
Fp in scala part 1Fp in scala part 1
Fp in scala part 1Hang Zhao
 
7 Habits For a More Functional Swift
7 Habits For a More Functional Swift7 Habits For a More Functional Swift
7 Habits For a More Functional SwiftJason Larsen
 
The Essence of the Iterator Pattern
The Essence of the Iterator PatternThe Essence of the Iterator Pattern
The Essence of the Iterator PatternEric Torreborre
 
Optics with monocle - Modeling the part and the whole
Optics with monocle - Modeling the part and the wholeOptics with monocle - Modeling the part and the whole
Optics with monocle - Modeling the part and the wholeIlan Godik
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsPhilip Schwarz
 
Type classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceType classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceAlexey Raga
 

Similar to Why The Free Monad isn't Free (20)

Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
 
Monad and Algebraic Design in Functional Programming
Monad and Algebraic Design in Functional ProgrammingMonad and Algebraic Design in Functional Programming
Monad and Algebraic Design in Functional Programming
 
Oh, All the things you'll traverse
Oh, All the things you'll traverseOh, All the things you'll traverse
Oh, All the things you'll traverse
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free Monads
 
Algebraic Data Types and Origami Patterns
Algebraic Data Types and Origami PatternsAlgebraic Data Types and Origami Patterns
Algebraic Data Types and Origami Patterns
 
Monads and friends demystified
Monads and friends demystifiedMonads and friends demystified
Monads and friends demystified
 
Kotlin Introduction with Android applications
Kotlin Introduction with Android applicationsKotlin Introduction with Android applications
Kotlin Introduction with Android applications
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monads
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final Tagless
 
Beyond Scala Lens
Beyond Scala LensBeyond Scala Lens
Beyond Scala Lens
 
Kleisli composition, flatMap, join, map, unit - implementation and interrelation
Kleisli composition, flatMap, join, map, unit - implementation and interrelationKleisli composition, flatMap, join, map, unit - implementation and interrelation
Kleisli composition, flatMap, join, map, unit - implementation and interrelation
 
All You Need is Fold
All You Need is FoldAll You Need is Fold
All You Need is Fold
 
Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adts
 
Scala best practices
Scala best practicesScala best practices
Scala best practices
 
Fp in scala part 1
Fp in scala part 1Fp in scala part 1
Fp in scala part 1
 
7 Habits For a More Functional Swift
7 Habits For a More Functional Swift7 Habits For a More Functional Swift
7 Habits For a More Functional Swift
 
The Essence of the Iterator Pattern
The Essence of the Iterator PatternThe Essence of the Iterator Pattern
The Essence of the Iterator Pattern
 
Optics with monocle - Modeling the part and the whole
Optics with monocle - Modeling the part and the wholeOptics with monocle - Modeling the part and the whole
Optics with monocle - Modeling the part and the whole
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
Type classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceType classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritance
 

More from Kelley Robinson

Protecting your phone verification flow from fraud & abuse
Protecting your phone verification flow from fraud & abuseProtecting your phone verification flow from fraud & abuse
Protecting your phone verification flow from fraud & abuseKelley Robinson
 
Preventing phone verification fraud (SMS pumping)
Preventing phone verification fraud (SMS pumping)Preventing phone verification fraud (SMS pumping)
Preventing phone verification fraud (SMS pumping)Kelley Robinson
 
Auth on the web: better authentication
Auth on the web: better authenticationAuth on the web: better authentication
Auth on the web: better authenticationKelley Robinson
 
Introduction to Public Key Cryptography
Introduction to Public Key CryptographyIntroduction to Public Key Cryptography
Introduction to Public Key CryptographyKelley Robinson
 
2FA in 2020 and Beyond
2FA in 2020 and Beyond2FA in 2020 and Beyond
2FA in 2020 and BeyondKelley Robinson
 
Identiverse 2020 - Account Recovery with 2FA
Identiverse 2020 - Account Recovery with 2FAIdentiverse 2020 - Account Recovery with 2FA
Identiverse 2020 - Account Recovery with 2FAKelley Robinson
 
Designing customer account recovery in a 2FA world
Designing customer account recovery in a 2FA worldDesigning customer account recovery in a 2FA world
Designing customer account recovery in a 2FA worldKelley Robinson
 
Introduction to SHAKEN/STIR
Introduction to SHAKEN/STIRIntroduction to SHAKEN/STIR
Introduction to SHAKEN/STIRKelley Robinson
 
Intro to SHAKEN/STIR
Intro to SHAKEN/STIRIntro to SHAKEN/STIR
Intro to SHAKEN/STIRKelley Robinson
 
Building a Better Scala Community
Building a Better Scala CommunityBuilding a Better Scala Community
Building a Better Scala CommunityKelley Robinson
 
BSides SF - Contact Center Authentication
BSides SF - Contact Center AuthenticationBSides SF - Contact Center Authentication
BSides SF - Contact Center AuthenticationKelley Robinson
 
Communication @ Startups
Communication @ StartupsCommunication @ Startups
Communication @ StartupsKelley Robinson
 
Contact Center Authentication
Contact Center AuthenticationContact Center Authentication
Contact Center AuthenticationKelley Robinson
 
Authentication Beyond SMS
Authentication Beyond SMSAuthentication Beyond SMS
Authentication Beyond SMSKelley Robinson
 
BSides PDX - Threat Modeling Authentication
BSides PDX - Threat Modeling AuthenticationBSides PDX - Threat Modeling Authentication
BSides PDX - Threat Modeling AuthenticationKelley Robinson
 
SIGNAL - Practical Cryptography
SIGNAL - Practical CryptographySIGNAL - Practical Cryptography
SIGNAL - Practical CryptographyKelley Robinson
 
2FA Best Practices
2FA Best Practices2FA Best Practices
2FA Best PracticesKelley Robinson
 
Practical Cryptography
Practical CryptographyPractical Cryptography
Practical CryptographyKelley Robinson
 

More from Kelley Robinson (20)

Protecting your phone verification flow from fraud & abuse
Protecting your phone verification flow from fraud & abuseProtecting your phone verification flow from fraud & abuse
Protecting your phone verification flow from fraud & abuse
 
Preventing phone verification fraud (SMS pumping)
Preventing phone verification fraud (SMS pumping)Preventing phone verification fraud (SMS pumping)
Preventing phone verification fraud (SMS pumping)
 
Auth on the web: better authentication
Auth on the web: better authenticationAuth on the web: better authentication
Auth on the web: better authentication
 
WebAuthn
WebAuthnWebAuthn
WebAuthn
 
Introduction to Public Key Cryptography
Introduction to Public Key CryptographyIntroduction to Public Key Cryptography
Introduction to Public Key Cryptography
 
2FA in 2020 and Beyond
2FA in 2020 and Beyond2FA in 2020 and Beyond
2FA in 2020 and Beyond
 
Identiverse 2020 - Account Recovery with 2FA
Identiverse 2020 - Account Recovery with 2FAIdentiverse 2020 - Account Recovery with 2FA
Identiverse 2020 - Account Recovery with 2FA
 
Designing customer account recovery in a 2FA world
Designing customer account recovery in a 2FA worldDesigning customer account recovery in a 2FA world
Designing customer account recovery in a 2FA world
 
Introduction to SHAKEN/STIR
Introduction to SHAKEN/STIRIntroduction to SHAKEN/STIR
Introduction to SHAKEN/STIR
 
Intro to SHAKEN/STIR
Intro to SHAKEN/STIRIntro to SHAKEN/STIR
Intro to SHAKEN/STIR
 
PSD2, SCA, WTF?
PSD2, SCA, WTF?PSD2, SCA, WTF?
PSD2, SCA, WTF?
 
Building a Better Scala Community
Building a Better Scala CommunityBuilding a Better Scala Community
Building a Better Scala Community
 
BSides SF - Contact Center Authentication
BSides SF - Contact Center AuthenticationBSides SF - Contact Center Authentication
BSides SF - Contact Center Authentication
 
Communication @ Startups
Communication @ StartupsCommunication @ Startups
Communication @ Startups
 
Contact Center Authentication
Contact Center AuthenticationContact Center Authentication
Contact Center Authentication
 
Authentication Beyond SMS
Authentication Beyond SMSAuthentication Beyond SMS
Authentication Beyond SMS
 
BSides PDX - Threat Modeling Authentication
BSides PDX - Threat Modeling AuthenticationBSides PDX - Threat Modeling Authentication
BSides PDX - Threat Modeling Authentication
 
SIGNAL - Practical Cryptography
SIGNAL - Practical CryptographySIGNAL - Practical Cryptography
SIGNAL - Practical Cryptography
 
2FA Best Practices
2FA Best Practices2FA Best Practices
2FA Best Practices
 
Practical Cryptography
Practical CryptographyPractical Cryptography
Practical Cryptography
 

Recently uploaded

Work Experience-Dalton Park.pptxfvvvvvvv
Work Experience-Dalton Park.pptxfvvvvvvvWork Experience-Dalton Park.pptxfvvvvvvv
Work Experience-Dalton Park.pptxfvvvvvvvLewisJB
 
Steel Structures - Building technology.pptx
Steel Structures - Building technology.pptxSteel Structures - Building technology.pptx
Steel Structures - Building technology.pptxNikhil Raut
 
Solving The Right Triangles PowerPoint 2.ppt
Solving The Right Triangles PowerPoint 2.pptSolving The Right Triangles PowerPoint 2.ppt
Solving The Right Triangles PowerPoint 2.pptJasonTagapanGulla
 
Research Methodology for Engineering pdf
Research Methodology for Engineering pdfResearch Methodology for Engineering pdf
Research Methodology for Engineering pdfCaalaaAbdulkerim
 
Internet of things -Arshdeep Bahga .pptx
Internet of things -Arshdeep Bahga .pptxInternet of things -Arshdeep Bahga .pptx
Internet of things -Arshdeep Bahga .pptxVelmuruganTECE
 
Call Girls Narol 7397865700 Independent Call Girls
Call Girls Narol 7397865700 Independent Call GirlsCall Girls Narol 7397865700 Independent Call Girls
Call Girls Narol 7397865700 Independent Call Girlsssuser7cb4ff
 
Software and Systems Engineering Standards: Verification and Validation of Sy...
Software and Systems Engineering Standards: Verification and Validation of Sy...Software and Systems Engineering Standards: Verification and Validation of Sy...
Software and Systems Engineering Standards: Verification and Validation of Sy...VICTOR MAESTRE RAMIREZ
 
Input Output Management in Operating System
Input Output Management in Operating SystemInput Output Management in Operating System
Input Output Management in Operating SystemRashmi Bhat
 
Class 1 | NFPA 72 | Overview Fire Alarm System
Class 1 | NFPA 72 | Overview Fire Alarm SystemClass 1 | NFPA 72 | Overview Fire Alarm System
Class 1 | NFPA 72 | Overview Fire Alarm Systemirfanmechengr
 
IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024Mark Billinghurst
 
Earthing details of Electrical Substation
Earthing details of Electrical SubstationEarthing details of Electrical Substation
Earthing details of Electrical Substationstephanwindworld
 
Industrial Safety Unit-IV workplace health and safety.ppt
Industrial Safety Unit-IV workplace health and safety.pptIndustrial Safety Unit-IV workplace health and safety.ppt
Industrial Safety Unit-IV workplace health and safety.pptNarmatha D
 
Unit7-DC_Motors nkkjnsdkfnfcdfknfdgfggfg
Unit7-DC_Motors nkkjnsdkfnfcdfknfdgfggfgUnit7-DC_Motors nkkjnsdkfnfcdfknfdgfggfg
Unit7-DC_Motors nkkjnsdkfnfcdfknfdgfggfgsaravananr517913
 
Arduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptArduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptSAURABHKUMAR892774
 
Introduction-To-Agricultural-Surveillance-Rover.pptx
Introduction-To-Agricultural-Surveillance-Rover.pptxIntroduction-To-Agricultural-Surveillance-Rover.pptx
Introduction-To-Agricultural-Surveillance-Rover.pptxk795866
 
Risk Assessment For Installation of Drainage Pipes.pdf
Risk Assessment For Installation of Drainage Pipes.pdfRisk Assessment For Installation of Drainage Pipes.pdf
Risk Assessment For Installation of Drainage Pipes.pdfROCENODodongVILLACER
 
Mine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxMine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxRomil Mishra
 

Recently uploaded (20)

Work Experience-Dalton Park.pptxfvvvvvvv
Work Experience-Dalton Park.pptxfvvvvvvvWork Experience-Dalton Park.pptxfvvvvvvv
Work Experience-Dalton Park.pptxfvvvvvvv
 
young call girls in Green Park🔝 9953056974 🔝 escort Service
young call girls in Green Park🔝 9953056974 🔝 escort Serviceyoung call girls in Green Park🔝 9953056974 🔝 escort Service
young call girls in Green Park🔝 9953056974 🔝 escort Service
 
Steel Structures - Building technology.pptx
Steel Structures - Building technology.pptxSteel Structures - Building technology.pptx
Steel Structures - Building technology.pptx
 
Solving The Right Triangles PowerPoint 2.ppt
Solving The Right Triangles PowerPoint 2.pptSolving The Right Triangles PowerPoint 2.ppt
Solving The Right Triangles PowerPoint 2.ppt
 
Research Methodology for Engineering pdf
Research Methodology for Engineering pdfResearch Methodology for Engineering pdf
Research Methodology for Engineering pdf
 
Internet of things -Arshdeep Bahga .pptx
Internet of things -Arshdeep Bahga .pptxInternet of things -Arshdeep Bahga .pptx
Internet of things -Arshdeep Bahga .pptx
 
Call Girls Narol 7397865700 Independent Call Girls
Call Girls Narol 7397865700 Independent Call GirlsCall Girls Narol 7397865700 Independent Call Girls
Call Girls Narol 7397865700 Independent Call Girls
 
Software and Systems Engineering Standards: Verification and Validation of Sy...
Software and Systems Engineering Standards: Verification and Validation of Sy...Software and Systems Engineering Standards: Verification and Validation of Sy...
Software and Systems Engineering Standards: Verification and Validation of Sy...
 
POWER SYSTEMS-1 Complete notes examples
POWER SYSTEMS-1 Complete notes  examplesPOWER SYSTEMS-1 Complete notes  examples
POWER SYSTEMS-1 Complete notes examples
 
Input Output Management in Operating System
Input Output Management in Operating SystemInput Output Management in Operating System
Input Output Management in Operating System
 
Class 1 | NFPA 72 | Overview Fire Alarm System
Class 1 | NFPA 72 | Overview Fire Alarm SystemClass 1 | NFPA 72 | Overview Fire Alarm System
Class 1 | NFPA 72 | Overview Fire Alarm System
 
IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024
 
Earthing details of Electrical Substation
Earthing details of Electrical SubstationEarthing details of Electrical Substation
Earthing details of Electrical Substation
 
Industrial Safety Unit-IV workplace health and safety.ppt
Industrial Safety Unit-IV workplace health and safety.pptIndustrial Safety Unit-IV workplace health and safety.ppt
Industrial Safety Unit-IV workplace health and safety.ppt
 
Design and analysis of solar grass cutter.pdf
Design and analysis of solar grass cutter.pdfDesign and analysis of solar grass cutter.pdf
Design and analysis of solar grass cutter.pdf
 
Unit7-DC_Motors nkkjnsdkfnfcdfknfdgfggfg
Unit7-DC_Motors nkkjnsdkfnfcdfknfdgfggfgUnit7-DC_Motors nkkjnsdkfnfcdfknfdgfggfg
Unit7-DC_Motors nkkjnsdkfnfcdfknfdgfggfg
 
Arduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptArduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.ppt
 
Introduction-To-Agricultural-Surveillance-Rover.pptx
Introduction-To-Agricultural-Surveillance-Rover.pptxIntroduction-To-Agricultural-Surveillance-Rover.pptx
Introduction-To-Agricultural-Surveillance-Rover.pptx
 
Risk Assessment For Installation of Drainage Pipes.pdf
Risk Assessment For Installation of Drainage Pipes.pdfRisk Assessment For Installation of Drainage Pipes.pdf
Risk Assessment For Installation of Drainage Pipes.pdf
 
Mine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxMine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptx
 

Why The Free Monad isn't Free

  • 1.
  • 2. [error] Exception encountered [error] java.lang.StackOverflowError
  • 3. WHY THE FREE MONAD ISN’T FREE “Let’s just trampoline it and add the Free Monad” @kelleyrobinson
  • 4. WHY THE FREE MONAD ISN’T FREE @kelleyrobinson “Let’s just trampoline it and add the Free Monad”
  • 5.
  • 6. Why The Free Monad Isn’t Free Kelley Robinson Data & Infrastructure Engineer Sharethrough @kelleyrobinson
  • 7. WHY THE FREE MONAD ISN’T FREE - Monoids, Functors & Monads - How to be “Free” - Why & Why Not “Free” - Alternatives - Real World Applications $ @kelleyrobinson
  • 8. WHY THE FREE MONAD ISN’T FREE github.com/robinske/monad-examples
  • 9. WHY THE FREE MONAD ISN’T FREE https://twitter.com/rickasaurus/status/705134684427128833
  • 10. WHY THE FREE MONAD ISN’T FREE Monoids @kelleyrobinson
  • 11. @kelleyrobinson trait Monoid[A] { 
 def append(a: A, b: A): A 
 def identity: A
 }
  • 12. WHY THE FREE MONAD ISN'T FREE Monoids Image credit: deluxebattery.com
  • 13. WHY THE FREE MONAD ISN'T FREE Properties Identity: "no-op" value Associativity: grouping doesn't matter @kelleyrobinson
  • 14. @kelleyrobinson object StringConcat extends Monoid[String] {
 
 def append(a: String, b: String): String = a + b
 
 def identity: String = ""
 
 }
  • 15. @kelleyrobinson object IntegerAddition extends Monoid[Int] {
 
 def append(a: Int, b: Int): Int = a + b
 
 def identity: Int = 0
 
 }
  • 16. @kelleyrobinson object IntegerMultiplication extends Monoid[Int] {
 
 def append(a: Int, b: Int): Int = a * b
 
 def identity: Int = 1
 
 }
  • 17. @kelleyrobinson object FunctionComposition /* extends Monoid[_=>_] */ {
 
 def append[A, B, C](f1: A => B, f2: B => C): A => C = (a: A) => f2(f1(a))
 
 def identity[A]: A => A = (a: A) => a 
 }
  • 18. @kelleyrobinson object FunctionComposition /* extends Monoid[_=>_] */ {
 
 def append[A, B, C](f1: A => B, f2: B => C): A => C = (a: A) => f2(f1(a))
 
 def identity[A]: A => A = (a: A) => a 
 }
  • 19. WHY THE FREE MONAD ISN’T FREE Functors @kelleyrobinson
  • 20. @kelleyrobinson trait Functor[F[_]] {
 
 def map[A, B](a: F[A])(fn: A => B): F[B]
 
 }
  • 21. WHY THE FREE MONAD ISN'T FREE @kelleyrobinson Properties Identity: "no-op" value Composition: grouping doesn't matter
  • 22. @kelleyrobinson sealed trait Option[+A]
 case class Some[A](a: A) extends Option[A]
 case object None extends Option[Nothing] object OptionFunctor extends Functor[Option] {
 
 def map[A, B](a: Option[A])(fn: A => B): Option[B] =
 a match {
 case Some(something) => Some(fn(something))
 case None => None
 }
 }
  • 23. @kelleyrobinson it("should follow the identity law") {
 def identity[A](a: A): A = a
 assert(map(Some("foo"))(identity) == Some("foo"))
 }
  • 24. @kelleyrobinson it("should follow the composition law") { val f: String => String = s => s + "a"
 val g: String => String = s => s + "l" val h: String => String = s => s + "a" assert( map(Some("sc"))(f andThen g andThen h) == map(map(map(Some("sc"))(f))(g))(h) == "scala" ) }
  • 25. Functors are Endofunctors** **in Scala WHY THE FREE MONAD ISN’T FREE @kelleyrobinson
  • 26. WHY THE FREE MONAD ISN’T FREE Monads @kelleyrobinson
  • 27. "The term monad is a bit vacuous if you are not a mathematician. An alternative term is computation builder." WHY THE FREE MONAD ISN’T FREE @kelleyrobinson http://stackoverflow.com/questions/44965/what-is-a-monad
  • 28. @kelleyrobinson trait Monad[M[_]] { 
 def pure[A](a: A): M[A]
 def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]
 }
  • 29. @kelleyrobinson sealed trait Option[+A]
 case class Some[A](a: A) extends Option[A]
 case object None extends Option[Nothing]
 
 object OptionMonad extends Monad[Option] {
 
 def pure[A](a: A): Option[A] = Some(a)
 
 def flatMap[A, B](a: Option[A])(fn: A => Option[B]): Option[B] =
 a match {
 case Some(something) => fn(something)
 case None => None
 }
 }
  • 30. @kelleyrobinson trait Monad[M[_]] { 
 def pure[A](a: A): M[A]
 def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]
 }
  • 31. @kelleyrobinson trait Monad[M[_]] {
 def pure[A](a: A): M[A]
 def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]
 
 def map[A, B](a: M[A])(fn: A => B): M[B] = {
 flatMap(a){ b: A => pure(fn(b)) }
 } 
 }
  • 32. @kelleyrobinson trait Monad[M[_]] { def pure[A](a: A): M[A]
 def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]
 
 def map[A, B](a: M[A])(fn: A => B): M[B] = {
 flatMap(a){ b: A => pure(fn(b)) }
 }
 }
  • 33. @kelleyrobinson trait Monad[M[_]] {
 def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]
 def append[A, B, C] (f1: A => M[B], f2: B => M[C]): A => M[C] = { a: A =>
 val bs: M[B] = f1(a)
 val cs: M[C] = flatMap(bs) { b: B => f2(b) }
 cs
 } 
 }
  • 34. @kelleyrobinson trait Monad[M[_]] {
 def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]
 def append[A, B, C] (f1: A => M[B], f2: B => M[C]): A => M[C] = { a: A =>
 val bs: M[B] = f1(a)
 val cs: M[C] = flatMap(bs) { b: B => f2(b) }
 cs
 } 
 }
  • 35. WHY THE FREE MONAD ISN'T FREE Properties Identity: "no-op" value Composition: grouping doesn't matter @kelleyrobinson
  • 36. WHY THE FREE MONAD ISN'T FREE Compose functions for values in a context Think: Lists, Options, Futures @kelleyrobinson
  • 37. trait Monad[M[_]] extends Functor[M] /* with Monoid[_=>M[_]] */ { 
 def pure[A](a: A): M[A]
 def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]
 
 def map[A, B](a: M[A])(fn: A => B): M[B]
 def append[A, B, C](f1: A => M[B], f2: B => M[C]): A => M[C]
 def identity[A]: A => M[A]
 } @kelleyrobinson trait Monad[M[_]] extends Functor[M] /* with Monoid[ _ => M[_] ] */ { 
 def pure[A](a: A): M[A]
 def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]
 
 def map[A, B](a: M[A])(fn: A => B): M[B]
 def append[A, B, C](f1: A => M[B], f2: B => M[C]): A => M[C]
 def identity[A]: A => M[A]
 }
  • 38. @kelleyrobinson trait Monad[M[_]] extends Functor[M] /* with Monoid[ _ => M[_] ] */ { 
 def pure[A](a: A): M[A]
 def flatMap[A, B](a: M[A])(fn: A => M[B]): M[B]
 
 def map[A, B](a: M[A])(fn: A => B): M[B]
 def append[A, B, C](f1: A => M[B], f2: B => M[C]): A => M[C]
 def identity[A]: A => M[A]
 }
  • 39. @kelleyrobinson object FunctionComposition /* extends Monoid[_ => _] */{
 
 ... } trait Monad[M[_]] /* extends Monoid[_ => M[_]] */{ 
 ... }
  • 40. WHY THE FREE MONAD ISN’T FREE - Monoids, Functors & Monads - How to be “Free” - Why & Why Not “Free” - Alternatives - Real World Applications $ @kelleyrobinson
  • 41. WHY THE FREE MONAD ISN'T FREE The word "free" is used in the sense of "unrestricted" rather than "zero-cost" $ @kelleyrobinson
  • 42. WHY THE FREE MONAD ISN'T FREE "Freedom not beer" https://en.wikipedia.org/wiki/Gratis_versus_libre#/media/File:Galuel_RMS_-_free_as_free_speech,_not_as_free_beer.png
  • 43. WHY THE FREE MONAD ISN’T FREE Free Monoids @kelleyrobinson
  • 44. @kelleyrobinson trait Monoid[A] { 
 def append(a: A, b: A): A
 def identity: A
 }
  • 45. WHY THE FREE MONAD ISN’T FREE Free Monoids • Free from interpretation • No lost input data when appending @kelleyrobinson image credit: http://celestemorris.com
  • 46. @kelleyrobinson // I'm free! class ListConcat[A] extends Monoid[List[A]] {
 def append(a: List[A], b: List[A]): List[A] = a ++ b
 def identity: List[A] = List.empty[A]
 }
  • 47. @kelleyrobinson // I'm not free :( object IntegerAddition extends Monoid[Int] {
 
 def append(a: Int, b: Int): Int = a + b
 
 def identity: Int = 0
 
 }
  • 48. WHY THE FREE MONAD ISN’T FREE Free Monads @kelleyrobinson
  • 49. Don't lose any data! (that means no evaluating functions) WHY THE FREE MONAD ISN’T FREE @kelleyrobinson
  • 50. @kelleyrobinson def notFreeAppend[A, B, C] (f1: A => M[B], f2: B => M[C]): A => M[C] = { a: A =>
 // evaluate f1 val bs: M[B] = f1(a) // evaluate f2
 val cs: M[C] = flatMap(bs) { b: B => f2(b) }
 cs }
  • 51. @kelleyrobinson sealed trait Free[F[_], A] { self =>
 
 }

  • 52. @kelleyrobinson sealed trait Free[F[_], A] { self =>
 }
 
 case class Return[F[_], A](given: A) extends Free[F, A]
  • 53. @kelleyrobinson sealed trait Free[F[_], A] { self =>
 
 }
 
 case class Return[F[_], A](given: A) extends Free[F, A] case class Suspend[F[_], A](fn: F[A]) extends Free[F, A]

  • 54. @kelleyrobinson sealed trait Free[F[_], A] { self =>
 
 }
 
 case class Return[F[_], A](given: A) extends Free[F, A] case class Suspend[F[_], A](fn: F[A]) extends Free[F, A]
 case class FlatMap[F[_], A, B] (free: Free[F, A], fn: A => Free[F, B]) extends Free[F, B]
  • 55. @kelleyrobinson sealed trait Free[F[_], A] { self => def flatMap ... def pure ... def map ... }
 
 case class Return[F[_], A](given: A) extends Free[F, A] case class Suspend[F[_], A](fn: F[A]) extends Free[F, A]
 case class FlatMap[F[_], A, B] (free: Free[F, A], fn: A => Free[F, B]) extends Free[F, B]
  • 56. @kelleyrobinson sealed trait Todo[A]
 case class NewTask[A](task: A) extends Todo[A]
 case class CompleteTask[A](task: A) extends Todo[A]
 case class GetTasks[A](default: A) extends Todo[A] def newTask[A](task: A): Free[Todo, A] = Suspend(NewTask(task))
 def completeTask[A](task: A): Free[Todo, A] = Suspend(CompleteTask(task))
 def getTasks[A](default: A): Free[Todo, A] = Suspend(GetTasks(default))
  • 57. @kelleyrobinson val todos: Free[Todo, Map[String, Boolean]] =
 for {
 _ <- newTask("Go to scala days")
 _ <- newTask("Write a novel")
 _ <- newTask("Meet Tina Fey")
 _ <- completeTask("Go to scala days")
 tsks <- getTasks(Map.empty)
 } yield tsks
  • 58. @kelleyrobinson val todosExpanded: Free[Todo, Map[String, Boolean]] =
 FlatMap(
 Suspend(NewTask("Go to scala days")), (a: String) =>
 FlatMap(
 Suspend(NewTask("Write a novel")), (b: String) =>
 FlatMap(
 Suspend(NewTask("Meet Tina Fey")), (c: String) =>
 FlatMap(
 Suspend(CompleteTask("Go to scala days")), (d: String) => Suspend(GetTasks(default = Map.empty))
 )
 )
 )
 )
  • 59. WHY THE FREE MONAD ISN’T FREE - Monoids, Functors & Monads - How to be “Free” - Why & Why Not “Free” - Alternatives - Real World Applications $ @kelleyrobinson
  • 60. WHY THE FREE MONAD ISN'T FREE What's the point? • Defer side effects • Multiple interpreters • Stack safety @kelleyrobinson
  • 61. @kelleyrobinson 
 (1 to 1000).flatMap { i =>
 doSomething(i).flatMap { j =>
 doSomethingElse(j).flatMap { k =>
 doAnotherThing(k).map { l =>
 ...
  • 62. WHY THE FREE MONAD ISN’T FREE “Let’s just trampoline it and add the Free Monad” @kelleyrobinson
  • 63. WHY THE FREE MONAD ISN’T FREE Trampolining Express it in a loop @kelleyrobinson
  • 64. WHY THE FREE MONAD ISN’T FREE The Free Monad uses heap instead of using stack. @kelleyrobinson
  • 65. @kelleyrobinson val todosExpanded: Free[Todo, Map[String, Boolean]] =
 FlatMap(
 Suspend(NewTask("Go to scala days")), (a: String) =>
 FlatMap(
 Suspend(NewTask("Write a novel")), (b: String) =>
 FlatMap(
 Suspend(NewTask("Meet Tina Fey")), (c: String) =>
 FlatMap(
 Suspend(CompleteTask("Go to scala days")), (d: String) => Suspend(GetTasks(default = Map.empty))
 )
 )
 )
 )
  • 66. WHY THE FREE MONAD ISN’T FREE @kelleyrobinson Evaluating Use a loop
  • 67. @kelleyrobinson def runFree[F[_], G[_], A] (f: Free[F, A]) (transform: FunctorTransformer[F, G]) (implicit G: Monad[G]): G[A]
  • 68. @kelleyrobinson def runFree[F[_], G[_], A] (f: Free[F, A]) (transform: FunctorTransformer[F, G]) (implicit G: Monad[G]): G[A] Turn F into G - AKA "Natural Transformation"Input `G` must be a monad so we can flatMap
  • 69. @kelleyrobinson // or 'NaturalTransformation'
 trait FunctorTransformer[F[_], G[_]] {
 def apply[A](f: F[A]): G[A]
 }
 // Common symbolic operator type ~>[F[_], G[_]] = FunctorTransformer[F, G]
  • 70. @kelleyrobinson /* Function body */ @annotation.tailrec
 def tailThis(free: Free[F, A]): Free[F, A] = free match {
 case FlatMap(FlatMap(fr, fn1), fn2) => ... case FlatMap(Return(a), fn) => ... case _ => ...
 }
 
 tailThis(f) match {
 case Return(a) => ...
 case Suspend(fa) => ... case FlatMap(Suspend(fa), fn) => ... case _ => ...
 } https://github.com/robinske/monad-examples
  • 71. @kelleyrobinson tailThis(f) match {
 case Return(a) => ...
 case Suspend(fa) => transform(fa) case FlatMap(Suspend(fa), fn) => monad.flatMap(transform(fa))(a => runFree(fn(a))(transform)) case _ => ...
 } https://github.com/robinske/monad-examples
  • 72. @kelleyrobinson def runLoop[F[_], G[_], A](...): G[A] = {
 var eval: Free[F, A] = f
 
 while (true) {
 eval match {
 case Return(a) => ...
 case Suspend(fa) => ...
 case FlatMap(Suspend(fa), fn) => ...
 case FlatMap(FlatMap(given, fn1), fn2) => ...
 case FlatMap(Return(s), fn) => ...
 }
 }
 
 throw new AssertionError("Unreachable")
 }
  • 73. WHY THE FREE MONAD ISN’T FREE @kelleyrobinson Evaluating Applies transformation on `Suspend` Trampolining for stack safety
  • 74. @kelleyrobinson // or 'NaturalTransformation'
 trait FunctorTransformer[F[_], G[_]] {
 def apply[A](f: F[A]): G[A]
 }
 // Common symbolic operator type ~>[F[_], G[_]] = FunctorTransformer[F, G]
  • 75. @kelleyrobinson type Id[A] = A case class TestEvaluator(var model: Map[String, Boolean]) extends FunctorTransformer[Todo, Id] {
 
 def apply[A](a: Todo[A]): Id[A] }
  • 76. @kelleyrobinson a match { case NewTask(task) =>
 model = model + (task.toString -> false)
 task
 case CompleteTask(task) =>
 model = model + (task.toString -> true)
 task
 case GetTasks(default) =>
 model.asInstanceOf[A] }
  • 77. @kelleyrobinson it("should evaluate todos") {
 val result = runFree(todos)(TestEvaluator(Map.empty))
 val expected: Map[String, Boolean] =
 Map(
 "Go to scala days" -> true,
 "Write a novel" -> false,
 "Meet Tina Fey" -> false
 )
 result shouldBe expected
 }
  • 78. @kelleyrobinson case object ActionTestEvaluator extends FunctorTransformer[Todo, Id] { 
 var actions: List[Todo[String]] = List.empty
 def apply[A](a: Todo[A]): Id[A] }
  • 79. @kelleyrobinson a match { case NewTask(task) =>
 actions = actions :+ NewTask(task.toString)
 task
 case CompleteTask(task) =>
 actions = actions :+ CompleteTask(task.toString)
 task
 case GetTasks(default) =>
 actions = actions :+ GetTasks("")
 default }
  • 80. @kelleyrobinson it("should evaluate todos actions in order") {
 runFree(todos)(ActionTestEvaluator)
 
 val expected: List[Todo[String]] =
 List(
 NewTask("Go to scala days"),
 NewTask("Write a novel"), NewTask("Meet Tina Fey"),
 CompleteTask("Go to scala days"), GetTasks("")
 ) 
 ActionTestEvaluator.actions shouldBe expected
 }
  • 81. WHY THE FREE MONAD ISN’T FREE @kelleyrobinson Defining multiple interpreters allows you to test side-effecting code without using testing mocks.
  • 82. @kelleyrobinson // Production Interpreter def apply[A](a: Todo[A]): Option[A] = {
 a match {
 case NewTask(task) =>
 /** * Some if DB write succeeds * None if DB write fails * */
 case CompleteTask(task) => ...
 case GetTasks(default) => ...
 }
 }
  • 83. WHY THE FREE MONAD ISN’T FREE @kelleyrobinson Justifications • Defer side effects • Multiple interpreters • Stack safety
  • 84. WHY THE FREE MONAD ISN'T FREE #BlueSkyScala The path to learning is broken @kelleyrobinson Credit: Jessica Kerr
  • 85. WHY THE FREE MONAD ISN'T FREE Freedom isn't free Reasons to avoid the Free Monad • Boilerplate • Learning curve • Alternatives @kelleyrobinson Credit: Jessica Kerr
  • 86. WHY THE FREE MONAD ISN’T FREE - Monoids, Functors & Monads - How to be “Free” - Why & Why Not “Free” - Alternatives - Real World Applications $ @kelleyrobinson
  • 87. WHY THE FREE MONAD ISN’T FREE @kelleyrobinson Know your domain
  • 88. WHY THE FREE MONAD ISN'T FREE Functional Spectrum Where does your team fall? Java Haskell
  • 89. WHY THE FREE MONAD ISN'T FREE Functional Spectrum Where does your team fall? Java Haskell
  • 90. WHY THE FREE MONAD ISN’T FREE @kelleyrobinson Alternatives for maintaining stack safety
  • 91. @kelleyrobinson final override def map[B, That](f: A => B) (implicit bf: CanBuildFrom[List[A], B, That]): That = {
 if (bf eq List.ReusableCBF) {
 if (this eq Nil) Nil.asInstanceOf[That] else {
 val h = new ::[B](f(head), Nil)
 var t: ::[B] = h
 var rest = tail
 while (rest ne Nil) {
 val nx = new ::(f(rest.head), Nil)
 t.tl = nx
 t = nx
 rest = rest.tail
 }
 h.asInstanceOf[That]
 }
 }
 else super.map(f)
 }
  • 92. WHY THE FREE MONAD ISN’T FREE @kelleyrobinson Alternatives for managing side effects
  • 93. @kelleyrobinson import java.sql.ResultSet
 
 case class Person(name: String, age: Int)
 
 def getPerson(rs: ResultSet): Person = {
 val name = rs.getString(1)
 val age = rs.getInt(2)
 Person(name, age)
 }
  • 94. @kelleyrobinson def handleFailure[A](f: => A): ActionResult / A = {
 Try(f) match {
 case Success(res) => res.right
 case Failure(e) => InternalServerError(reason = e.getMessage).left
 }
 } 
 handleFailure(getPerson(rs))
  • 95. WHY THE FREE MONAD ISN’T FREE - Monoids, Functors & Monads - How to be “Free” - Why & Why Not “Free” - Alternatives - Real World Applications $ @kelleyrobinson
  • 96. WHY THE FREE MONAD ISN'T FREE Scalaz Scalaz is a Scala library for functional programming. http://scalaz.github.io/scalaz/ Cats Lightweight, modular, and extensible library for functional programming. http://typelevel.org/cats/ @kelleyrobinson http://www.slideshare.net/jamesskillsmatter/real-world-scalaz
  • 97. WHY THE FREE MONAD ISN'T FREE Examples • Doobie • scalaz.concurrent.Task @kelleyrobinson https://github.com/tpolecat/doobie
  • 98. @kelleyrobinson import scalaz.concurrent.Task def apply(conf: Config, messages: List[SQSMessage]): Unit = {
 val tasks = messages.map(m => Task {
 processSQSMessage(conf, m)
 })
 
 Task.gatherUnordered(tasks).attemptRun match {
 case -/(exp) => error(s"Unable to process message")
 case _ => ()
 }
 }
  • 99. @kelleyrobinson // yikes object Task {
 implicit val taskInstance: Nondeterminism[Task] with Catchable[Task] with MonadError[({type λ[α,β] = Task[β]})#λ,Throwable] = new Nondeterminism[Task] with Catchable[Task] with MonadError[({type λ[α,β] = Task[β]})#λ,Throwable] { ... } }
  • 100. WHY THE FREE MONAD ISN’T FREE @kelleyrobinson My experience... ...what happened?
  • 101. WHY THE FREE MONAD ISN’T FREE - Know your domain - Use clean abstractions - Share knowledge $ @kelleyrobinson
  • 103. WHY THE FREE MONAD ISN’T FREE @kelleyrobinson Acknowledgements & Resources Special thanks to: • Sharethrough • RĂşnar Bjarnason • Rob Norris • Eugene Yokota • Jessica Kerr • David Hoyt • Danielle Sucher • Charles Ruhland Resources for learning more about Free Monads: • http://blog.higher-order.com/assets/trampolines.pdf • http://eed3si9n.com/learning-scalaz/ • https://stackoverflow.com/questions/44965/what-is-a-monad • https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/ • http://hseeberger.github.io/blog/2010/11/25/introduction-to-category-theory-in-scala/ • https://en.wikipedia.org/wiki/Free_object • https://softwaremill.com/free-monads/ • https://github.com/davidhoyt/kool-aid/ • https://www.youtube.com/watch?v=T4956GI-6Lw Other links and resources: • https://skillsmatter.com/skillscasts/6483-keynote-scaling-intelligence-moving-ideas-forward • https://stackoverflow.com/questions/7213676/forall-in-scala but that boilerplate