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

Taking your side effects aside
Taking your side effects asideTaking your side effects aside
Taking your side effects aside💡 Tomasz Kogut
 
Gentle Introduction to Scala
Gentle Introduction to ScalaGentle Introduction to Scala
Gentle Introduction to ScalaFangda Wang
 
Property Based Testing in PHP
Property Based Testing in PHPProperty Based Testing in PHP
Property Based Testing in PHPvinaikopp
 
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
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayDebasish Ghosh
 
non-strict functions, bottom and scala by-name parameters
non-strict functions, bottom and scala by-name parametersnon-strict functions, bottom and scala by-name parameters
non-strict functions, bottom and scala by-name parametersPhilip Schwarz
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Philip Schwarz
 
Working With a Real-World Dataset in Neo4j: Import and Modeling
Working With a Real-World Dataset in Neo4j: Import and ModelingWorking With a Real-World Dataset in Neo4j: Import and Modeling
Working With a Real-World Dataset in Neo4j: Import and ModelingNeo4j
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Philip Schwarz
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018John De Goes
 
Introduction to SQL Antipatterns
Introduction to SQL AntipatternsIntroduction to SQL Antipatterns
Introduction to SQL AntipatternsKrishnakumar S
 
Kotlin as a Better Java
Kotlin as a Better JavaKotlin as a Better Java
Kotlin as a Better JavaGarth Gilmour
 
Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsAlgebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsDebasish Ghosh
 

What's hot (20)

Taking your side effects aside
Taking your side effects asideTaking your side effects aside
Taking your side effects aside
 
Gentle Introduction to Scala
Gentle Introduction to ScalaGentle Introduction to Scala
Gentle Introduction to Scala
 
Property Based Testing in PHP
Property Based Testing in PHPProperty Based Testing in PHP
Property Based Testing in PHP
 
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
 
Scala collection
Scala collectionScala collection
Scala collection
 
Zio in real world
Zio in real worldZio in real world
Zio in real world
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
 
Load Data Fast!
Load Data Fast!Load Data Fast!
Load Data Fast!
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
non-strict functions, bottom and scala by-name parameters
non-strict functions, bottom and scala by-name parametersnon-strict functions, bottom and scala by-name parameters
non-strict functions, bottom and scala by-name parameters
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
 
Working With a Real-World Dataset in Neo4j: Import and Modeling
Working With a Real-World Dataset in Neo4j: Import and ModelingWorking With a Real-World Dataset in Neo4j: Import and Modeling
Working With a Real-World Dataset in Neo4j: Import and Modeling
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
 
Scala Intro
Scala IntroScala Intro
Scala Intro
 
Arrays in Java
Arrays in Java Arrays in Java
Arrays in Java
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
Practical Object Oriented Models In Sql
Practical Object Oriented Models In SqlPractical Object Oriented Models In Sql
Practical Object Oriented Models In Sql
 
Introduction to SQL Antipatterns
Introduction to SQL AntipatternsIntroduction to SQL Antipatterns
Introduction to SQL Antipatterns
 
Kotlin as a Better Java
Kotlin as a Better JavaKotlin as a Better Java
Kotlin as a Better Java
 
Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsAlgebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain Models
 

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
 
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
 
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
 
The Essence of the Iterator Pattern (pdf)
The Essence of the Iterator Pattern (pdf)The Essence of the Iterator Pattern (pdf)
The Essence of the Iterator Pattern (pdf)Eric Torreborre
 

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
 
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
 
The Essence of the Iterator Pattern (pdf)
The Essence of the Iterator Pattern (pdf)The Essence of the Iterator Pattern (pdf)
The Essence of the Iterator Pattern (pdf)
 

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
 
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
 
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
 

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

8th International Conference on Soft Computing, Mathematics and Control (SMC ...
8th International Conference on Soft Computing, Mathematics and Control (SMC ...8th International Conference on Soft Computing, Mathematics and Control (SMC ...
8th International Conference on Soft Computing, Mathematics and Control (SMC ...josephjonse
 
The battle for RAG, explore the pros and cons of using KnowledgeGraphs and Ve...
The battle for RAG, explore the pros and cons of using KnowledgeGraphs and Ve...The battle for RAG, explore the pros and cons of using KnowledgeGraphs and Ve...
The battle for RAG, explore the pros and cons of using KnowledgeGraphs and Ve...Roi Lipman
 
analog-vs-digital-communication (concept of analog and digital).pptx
analog-vs-digital-communication (concept of analog and digital).pptxanalog-vs-digital-communication (concept of analog and digital).pptx
analog-vs-digital-communication (concept of analog and digital).pptxKarpagam Institute of Teechnology
 
Electrical shop management system project report.pdf
Electrical shop management system project report.pdfElectrical shop management system project report.pdf
Electrical shop management system project report.pdfKamal Acharya
 
Seizure stage detection of epileptic seizure using convolutional neural networks
Seizure stage detection of epileptic seizure using convolutional neural networksSeizure stage detection of epileptic seizure using convolutional neural networks
Seizure stage detection of epileptic seizure using convolutional neural networksIJECEIAES
 
Piping and instrumentation diagram p.pdf
Piping and instrumentation diagram p.pdfPiping and instrumentation diagram p.pdf
Piping and instrumentation diagram p.pdfAshrafRagab14
 
Final DBMS Manual (2).pdf final lab manual
Final DBMS Manual (2).pdf final lab manualFinal DBMS Manual (2).pdf final lab manual
Final DBMS Manual (2).pdf final lab manualBalamuruganV28
 
Tembisa Central Terminating Pills +27838792658 PHOMOLONG Top Abortion Pills F...
Tembisa Central Terminating Pills +27838792658 PHOMOLONG Top Abortion Pills F...Tembisa Central Terminating Pills +27838792658 PHOMOLONG Top Abortion Pills F...
Tembisa Central Terminating Pills +27838792658 PHOMOLONG Top Abortion Pills F...drjose256
 
Passive Air Cooling System and Solar Water Heater.ppt
Passive Air Cooling System and Solar Water Heater.pptPassive Air Cooling System and Solar Water Heater.ppt
Passive Air Cooling System and Solar Water Heater.pptamrabdallah9
 
Raashid final report on Embedded Systems
Raashid final report on Embedded SystemsRaashid final report on Embedded Systems
Raashid final report on Embedded SystemsRaashidFaiyazSheikh
 
UNIT-2 image enhancement.pdf Image Processing Unit 2 AKTU
UNIT-2 image enhancement.pdf Image Processing Unit 2 AKTUUNIT-2 image enhancement.pdf Image Processing Unit 2 AKTU
UNIT-2 image enhancement.pdf Image Processing Unit 2 AKTUankushspencer015
 
1893-part-1-2016 for Earthquake load design
1893-part-1-2016 for Earthquake load design1893-part-1-2016 for Earthquake load design
1893-part-1-2016 for Earthquake load designAshishSingh1301
 
Worksharing and 3D Modeling with Revit.pptx
Worksharing and 3D Modeling with Revit.pptxWorksharing and 3D Modeling with Revit.pptx
Worksharing and 3D Modeling with Revit.pptxMustafa Ahmed
 
Online crime reporting system project.pdf
Online crime reporting system project.pdfOnline crime reporting system project.pdf
Online crime reporting system project.pdfKamal Acharya
 
Module-III Varried Flow.pptx GVF Definition, Water Surface Profile Dynamic Eq...
Module-III Varried Flow.pptx GVF Definition, Water Surface Profile Dynamic Eq...Module-III Varried Flow.pptx GVF Definition, Water Surface Profile Dynamic Eq...
Module-III Varried Flow.pptx GVF Definition, Water Surface Profile Dynamic Eq...Nitin Sonavane
 
electrical installation and maintenance.
electrical installation and maintenance.electrical installation and maintenance.
electrical installation and maintenance.benjamincojr
 
Activity Planning: Objectives, Project Schedule, Network Planning Model. Time...
Activity Planning: Objectives, Project Schedule, Network Planning Model. Time...Activity Planning: Objectives, Project Schedule, Network Planning Model. Time...
Activity Planning: Objectives, Project Schedule, Network Planning Model. Time...Lovely Professional University
 
Research Methodolgy & Intellectual Property Rights Series 1
Research Methodolgy & Intellectual Property Rights Series 1Research Methodolgy & Intellectual Property Rights Series 1
Research Methodolgy & Intellectual Property Rights Series 1T.D. Shashikala
 
Operating System chapter 9 (Virtual Memory)
Operating System chapter 9 (Virtual Memory)Operating System chapter 9 (Virtual Memory)
Operating System chapter 9 (Virtual Memory)NareenAsad
 
ALCOHOL PRODUCTION- Beer Brewing Process.pdf
ALCOHOL PRODUCTION- Beer Brewing Process.pdfALCOHOL PRODUCTION- Beer Brewing Process.pdf
ALCOHOL PRODUCTION- Beer Brewing Process.pdfMadan Karki
 

Recently uploaded (20)

8th International Conference on Soft Computing, Mathematics and Control (SMC ...
8th International Conference on Soft Computing, Mathematics and Control (SMC ...8th International Conference on Soft Computing, Mathematics and Control (SMC ...
8th International Conference on Soft Computing, Mathematics and Control (SMC ...
 
The battle for RAG, explore the pros and cons of using KnowledgeGraphs and Ve...
The battle for RAG, explore the pros and cons of using KnowledgeGraphs and Ve...The battle for RAG, explore the pros and cons of using KnowledgeGraphs and Ve...
The battle for RAG, explore the pros and cons of using KnowledgeGraphs and Ve...
 
analog-vs-digital-communication (concept of analog and digital).pptx
analog-vs-digital-communication (concept of analog and digital).pptxanalog-vs-digital-communication (concept of analog and digital).pptx
analog-vs-digital-communication (concept of analog and digital).pptx
 
Electrical shop management system project report.pdf
Electrical shop management system project report.pdfElectrical shop management system project report.pdf
Electrical shop management system project report.pdf
 
Seizure stage detection of epileptic seizure using convolutional neural networks
Seizure stage detection of epileptic seizure using convolutional neural networksSeizure stage detection of epileptic seizure using convolutional neural networks
Seizure stage detection of epileptic seizure using convolutional neural networks
 
Piping and instrumentation diagram p.pdf
Piping and instrumentation diagram p.pdfPiping and instrumentation diagram p.pdf
Piping and instrumentation diagram p.pdf
 
Final DBMS Manual (2).pdf final lab manual
Final DBMS Manual (2).pdf final lab manualFinal DBMS Manual (2).pdf final lab manual
Final DBMS Manual (2).pdf final lab manual
 
Tembisa Central Terminating Pills +27838792658 PHOMOLONG Top Abortion Pills F...
Tembisa Central Terminating Pills +27838792658 PHOMOLONG Top Abortion Pills F...Tembisa Central Terminating Pills +27838792658 PHOMOLONG Top Abortion Pills F...
Tembisa Central Terminating Pills +27838792658 PHOMOLONG Top Abortion Pills F...
 
Passive Air Cooling System and Solar Water Heater.ppt
Passive Air Cooling System and Solar Water Heater.pptPassive Air Cooling System and Solar Water Heater.ppt
Passive Air Cooling System and Solar Water Heater.ppt
 
Raashid final report on Embedded Systems
Raashid final report on Embedded SystemsRaashid final report on Embedded Systems
Raashid final report on Embedded Systems
 
UNIT-2 image enhancement.pdf Image Processing Unit 2 AKTU
UNIT-2 image enhancement.pdf Image Processing Unit 2 AKTUUNIT-2 image enhancement.pdf Image Processing Unit 2 AKTU
UNIT-2 image enhancement.pdf Image Processing Unit 2 AKTU
 
1893-part-1-2016 for Earthquake load design
1893-part-1-2016 for Earthquake load design1893-part-1-2016 for Earthquake load design
1893-part-1-2016 for Earthquake load design
 
Worksharing and 3D Modeling with Revit.pptx
Worksharing and 3D Modeling with Revit.pptxWorksharing and 3D Modeling with Revit.pptx
Worksharing and 3D Modeling with Revit.pptx
 
Online crime reporting system project.pdf
Online crime reporting system project.pdfOnline crime reporting system project.pdf
Online crime reporting system project.pdf
 
Module-III Varried Flow.pptx GVF Definition, Water Surface Profile Dynamic Eq...
Module-III Varried Flow.pptx GVF Definition, Water Surface Profile Dynamic Eq...Module-III Varried Flow.pptx GVF Definition, Water Surface Profile Dynamic Eq...
Module-III Varried Flow.pptx GVF Definition, Water Surface Profile Dynamic Eq...
 
electrical installation and maintenance.
electrical installation and maintenance.electrical installation and maintenance.
electrical installation and maintenance.
 
Activity Planning: Objectives, Project Schedule, Network Planning Model. Time...
Activity Planning: Objectives, Project Schedule, Network Planning Model. Time...Activity Planning: Objectives, Project Schedule, Network Planning Model. Time...
Activity Planning: Objectives, Project Schedule, Network Planning Model. Time...
 
Research Methodolgy & Intellectual Property Rights Series 1
Research Methodolgy & Intellectual Property Rights Series 1Research Methodolgy & Intellectual Property Rights Series 1
Research Methodolgy & Intellectual Property Rights Series 1
 
Operating System chapter 9 (Virtual Memory)
Operating System chapter 9 (Virtual Memory)Operating System chapter 9 (Virtual Memory)
Operating System chapter 9 (Virtual Memory)
 
ALCOHOL PRODUCTION- Beer Brewing Process.pdf
ALCOHOL PRODUCTION- Beer Brewing Process.pdfALCOHOL PRODUCTION- Beer Brewing Process.pdf
ALCOHOL PRODUCTION- Beer Brewing Process.pdf
 

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