SlideShare une entreprise Scribd logo
1  sur  103
Télécharger pour lire hors ligne
[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

Contenu connexe

Tendances

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
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with SpringJoshua Long
 
Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)Hermann Hueck
 
Functional Error Handling with Cats
Functional Error Handling with CatsFunctional Error Handling with Cats
Functional Error Handling with CatsMark Canlas
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Philip Schwarz
 
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021Natan Silnitsky
 
Intro to Pentesting Jenkins
Intro to Pentesting JenkinsIntro to Pentesting Jenkins
Intro to Pentesting JenkinsBrian Hysell
 
Py.test
Py.testPy.test
Py.testsoasme
 
Using hilt in a modularized project
Using hilt in a modularized projectUsing hilt in a modularized project
Using hilt in a modularized projectFabio Collini
 
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
 
Implementing the IO Monad in Scala
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in ScalaHermann Hueck
 
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin CoroutinesThreading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin CoroutinesLauren Yew
 
Introduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platformIntroduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platformEastBanc Tachnologies
 
Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kros Huang
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Languageintelliyole
 
Testing in-python-and-pytest-framework
Testing in-python-and-pytest-frameworkTesting in-python-and-pytest-framework
Testing in-python-and-pytest-frameworkArulalan T
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022Alexander Ioffe
 

Tendances (20)

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
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
 
Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)
 
Functional Error Handling with Cats
Functional Error Handling with CatsFunctional Error Handling with Cats
Functional Error Handling with Cats
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
 
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
 
Intro to Pentesting Jenkins
Intro to Pentesting JenkinsIntro to Pentesting Jenkins
Intro to Pentesting Jenkins
 
Py.test
Py.testPy.test
Py.test
 
Using hilt in a modularized project
Using hilt in a modularized projectUsing hilt in a modularized project
Using hilt in a modularized project
 
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
 
Implementing the IO Monad in Scala
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in Scala
 
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin CoroutinesThreading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
 
Introduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platformIntroduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platform
 
Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹
 
Intro to kotlin
Intro to kotlinIntro to kotlin
Intro to kotlin
 
Monads do not Compose
Monads do not ComposeMonads do not Compose
Monads do not Compose
 
ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Language
 
Testing in-python-and-pytest-framework
Testing in-python-and-pytest-frameworkTesting in-python-and-pytest-framework
Testing in-python-and-pytest-framework
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022
 

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

Similaire à 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
 
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)
 

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

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

Dernier

Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxStephen Sitton
 
Guardians of E-Commerce: Harnessing NLP and Machine Learning Approaches for A...
Guardians of E-Commerce: Harnessing NLP and Machine Learning Approaches for A...Guardians of E-Commerce: Harnessing NLP and Machine Learning Approaches for A...
Guardians of E-Commerce: Harnessing NLP and Machine Learning Approaches for A...IJAEMSJORNAL
 
Artificial Intelligence in Power System overview
Artificial Intelligence in Power System overviewArtificial Intelligence in Power System overview
Artificial Intelligence in Power System overviewsandhya757531
 
1- Practice occupational health and safety procedures.pptx
1- Practice occupational health and safety procedures.pptx1- Practice occupational health and safety procedures.pptx
1- Practice occupational health and safety procedures.pptxMel Paras
 
Uk-NO1 kala jadu karne wale ka contact number kala jadu karne wale baba kala ...
Uk-NO1 kala jadu karne wale ka contact number kala jadu karne wale baba kala ...Uk-NO1 kala jadu karne wale ka contact number kala jadu karne wale baba kala ...
Uk-NO1 kala jadu karne wale ka contact number kala jadu karne wale baba kala ...Amil baba
 
70 POWER PLANT IAE V2500 technical training
70 POWER PLANT IAE V2500 technical training70 POWER PLANT IAE V2500 technical training
70 POWER PLANT IAE V2500 technical trainingGladiatorsKasper
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTSneha Padhiar
 
Introduction of Object Oriented Programming Language using Java. .pptx
Introduction of Object Oriented Programming Language using Java. .pptxIntroduction of Object Oriented Programming Language using Java. .pptx
Introduction of Object Oriented Programming Language using Java. .pptxPoonam60376
 
Cost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionCost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionSneha Padhiar
 
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfComprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfalene1
 
22CYT12 & Chemistry for Computer Systems_Unit-II-Corrosion & its Control Meth...
22CYT12 & Chemistry for Computer Systems_Unit-II-Corrosion & its Control Meth...22CYT12 & Chemistry for Computer Systems_Unit-II-Corrosion & its Control Meth...
22CYT12 & Chemistry for Computer Systems_Unit-II-Corrosion & its Control Meth...KrishnaveniKrishnara1
 
Structural Integrity Assessment Standards in Nigeria by Engr Nimot Muili
Structural Integrity Assessment Standards in Nigeria by Engr Nimot MuiliStructural Integrity Assessment Standards in Nigeria by Engr Nimot Muili
Structural Integrity Assessment Standards in Nigeria by Engr Nimot MuiliNimot Muili
 
AntColonyOptimizationManetNetworkAODV.pptx
AntColonyOptimizationManetNetworkAODV.pptxAntColonyOptimizationManetNetworkAODV.pptx
AntColonyOptimizationManetNetworkAODV.pptxLina Kadam
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSneha Padhiar
 
Novel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsNovel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsResearcher Researcher
 
Machine Learning 5G Federated Learning.pdf
Machine Learning 5G Federated Learning.pdfMachine Learning 5G Federated Learning.pdf
Machine Learning 5G Federated Learning.pdfadeyimikaipaye
 
Theory of Machine Notes / Lecture Material .pdf
Theory of Machine Notes / Lecture Material .pdfTheory of Machine Notes / Lecture Material .pdf
Theory of Machine Notes / Lecture Material .pdfShreyas Pandit
 
Introduction to Machine Learning Part1.pptx
Introduction to Machine Learning Part1.pptxIntroduction to Machine Learning Part1.pptx
Introduction to Machine Learning Part1.pptxPavan Mohan Neelamraju
 

Dernier (20)

Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptx
 
Guardians of E-Commerce: Harnessing NLP and Machine Learning Approaches for A...
Guardians of E-Commerce: Harnessing NLP and Machine Learning Approaches for A...Guardians of E-Commerce: Harnessing NLP and Machine Learning Approaches for A...
Guardians of E-Commerce: Harnessing NLP and Machine Learning Approaches for A...
 
Artificial Intelligence in Power System overview
Artificial Intelligence in Power System overviewArtificial Intelligence in Power System overview
Artificial Intelligence in Power System overview
 
1- Practice occupational health and safety procedures.pptx
1- Practice occupational health and safety procedures.pptx1- Practice occupational health and safety procedures.pptx
1- Practice occupational health and safety procedures.pptx
 
Uk-NO1 kala jadu karne wale ka contact number kala jadu karne wale baba kala ...
Uk-NO1 kala jadu karne wale ka contact number kala jadu karne wale baba kala ...Uk-NO1 kala jadu karne wale ka contact number kala jadu karne wale baba kala ...
Uk-NO1 kala jadu karne wale ka contact number kala jadu karne wale baba kala ...
 
70 POWER PLANT IAE V2500 technical training
70 POWER PLANT IAE V2500 technical training70 POWER PLANT IAE V2500 technical training
70 POWER PLANT IAE V2500 technical training
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
 
Introduction of Object Oriented Programming Language using Java. .pptx
Introduction of Object Oriented Programming Language using Java. .pptxIntroduction of Object Oriented Programming Language using Java. .pptx
Introduction of Object Oriented Programming Language using Java. .pptx
 
Cost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionCost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based question
 
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfComprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
 
22CYT12 & Chemistry for Computer Systems_Unit-II-Corrosion & its Control Meth...
22CYT12 & Chemistry for Computer Systems_Unit-II-Corrosion & its Control Meth...22CYT12 & Chemistry for Computer Systems_Unit-II-Corrosion & its Control Meth...
22CYT12 & Chemistry for Computer Systems_Unit-II-Corrosion & its Control Meth...
 
Structural Integrity Assessment Standards in Nigeria by Engr Nimot Muili
Structural Integrity Assessment Standards in Nigeria by Engr Nimot MuiliStructural Integrity Assessment Standards in Nigeria by Engr Nimot Muili
Structural Integrity Assessment Standards in Nigeria by Engr Nimot Muili
 
AntColonyOptimizationManetNetworkAODV.pptx
AntColonyOptimizationManetNetworkAODV.pptxAntColonyOptimizationManetNetworkAODV.pptx
AntColonyOptimizationManetNetworkAODV.pptx
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
 
Versatile Engineering Construction Firms
Versatile Engineering Construction FirmsVersatile Engineering Construction Firms
Versatile Engineering Construction Firms
 
Novel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsNovel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending Actuators
 
Machine Learning 5G Federated Learning.pdf
Machine Learning 5G Federated Learning.pdfMachine Learning 5G Federated Learning.pdf
Machine Learning 5G Federated Learning.pdf
 
ASME-B31.4-2019-estandar para diseño de ductos
ASME-B31.4-2019-estandar para diseño de ductosASME-B31.4-2019-estandar para diseño de ductos
ASME-B31.4-2019-estandar para diseño de ductos
 
Theory of Machine Notes / Lecture Material .pdf
Theory of Machine Notes / Lecture Material .pdfTheory of Machine Notes / Lecture Material .pdf
Theory of Machine Notes / Lecture Material .pdf
 
Introduction to Machine Learning Part1.pptx
Introduction to Machine Learning Part1.pptxIntroduction to Machine Learning Part1.pptx
Introduction to Machine Learning Part1.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