curry on 2016 - why the free monad isn't free

103
Why The Free Monad Isn’t Free

Upload: kelley-robinson

Post on 09-Jan-2017

713 views

Category:

Engineering


0 download

TRANSCRIPT

Page 1: Curry On 2016 - Why the Free Monad isn't Free

Why The Free Monad Isn’t Free

Page 2: Curry On 2016 - Why the Free Monad isn't Free
Page 3: Curry On 2016 - Why the Free Monad isn't Free

[error] Exception encountered [error] java.lang.StackOverflowError

Page 4: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

“Let’s just trampoline it and add the Free Monad”

@kelleyrobinson

Page 5: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

“Let’s just trampoline it and add the Free Monad”

Page 6: Curry On 2016 - Why the Free Monad isn't Free
Page 7: Curry On 2016 - Why the Free Monad isn't Free

Why The Free Monad Isn’t Free

Kelley Robinson Data & Infrastructure Engineer

Sharethrough

@kelleyrobinson

Page 8: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

- Monoids, Functors & Monads

- How to be “Free”

- Why & Why Not “Free”

- Alternatives

- Real World Applications

$

@kelleyrobinson

Page 9: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

github.com/robinske/monad-examples

Page 10: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

https://twitter.com/rickasaurus/status/705134684427128833

Page 11: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

Monoids

@kelleyrobinson

Page 12: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

trait Monoid[A] { def append(a: A, b: A): A def identity: A

}

Page 13: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

Monoids

Image credit: deluxebattery.com

Page 14: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

Properties

Identity: "no-op" value

Associativity: grouping doesn't matter

@kelleyrobinson

Page 15: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

object StringConcat extends Monoid[String] { def append(a: String, b: String): String = a + b def identity: String = "" }

Page 16: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

object IntegerAddition extends Monoid[Int] { def append(a: Int, b: Int): Int = a + b def identity: Int = 0 }

Page 17: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

Functors

@kelleyrobinson

Page 18: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

trait Functor[F[_]] { def map[A, B](a: F[A])(fn: A => B): F[B] }

Page 19: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

1

2 3

2

4 6

value*2

map

Page 20: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

@kelleyrobinson

Properties

Identity: "no-op" value

Composition: grouping doesn't matter

Page 21: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

Monads

@kelleyrobinson

Page 22: Curry On 2016 - Why the Free Monad isn't Free

"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

Page 23: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

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

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

}

Page 24: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

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

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

}

Page 25: Curry On 2016 - Why the Free Monad isn't Free

@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)) } } }

Page 26: Curry On 2016 - Why the Free Monad isn't Free

@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)) } }

}

Page 27: Curry On 2016 - Why the Free Monad isn't Free

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

Page 28: Curry On 2016 - Why the Free Monad isn't Free

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

Page 29: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

Properties

Identity: "no-op" value

Composition: grouping doesn't matter

@kelleyrobinson

Page 30: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

1

2 3

2

4 6

value*2

map (functor)

Page 31: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

1

2 3

2

4 6value*2

map

Page 32: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

flatMap

@kelleyrobinson@kelleyrobinson

1

2 3

2

4 6value*2

Page 33: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

Compose functions for values in a context

Think: Lists, Futures

@kelleyrobinson

Page 34: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

- Monoids, Functors & Monads

- How to be “Free”

- Why & Why Not “Free”

- Alternatives

- Real World Applications

$

@kelleyrobinson

Page 35: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

The word "free" is used in the sense of "unrestricted" rather than "zero-cost"

$

@kelleyrobinson

Page 36: Curry On 2016 - Why the Free Monad isn't Free

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

Page 37: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

Free Monoids

@kelleyrobinson

Page 38: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

trait Monoid[A] { def append(a: A, b: A): A def identity: A

}

Page 39: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

Free Monoids • Free from interpretation

• No lost input data when

appending

@kelleyrobinson

image credit: http://celestemorris.com

Page 40: Curry On 2016 - Why the Free Monad isn't Free

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

}

Page 41: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

// I'm not free :(

object IntegerAddition extends Monoid[Int] { def append(a: Int, b: Int): Int = a + b def identity: Int = 0 }

Page 42: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

Free Monads

@kelleyrobinson

Page 43: Curry On 2016 - Why the Free Monad isn't Free

Don't lose any data! (that means no evaluating functions)

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

Page 44: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

flatMap

@kelleyrobinson

1

2 3

2

4 6

fn:

value* 2

Page 45: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

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

}

Page 46: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

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

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

Page 47: Curry On 2016 - Why the Free Monad isn't Free

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

Page 48: Curry On 2016 - Why the Free Monad isn't Free

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

Page 49: Curry On 2016 - Why the Free Monad isn't Free

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

Page 50: Curry On 2016 - Why the Free Monad isn't Free

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

Page 51: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

val todos: Free[Todo, Map[String, Boolean]] = for { _ <- newTask("Go to Curry On") _ <- newTask("Write a novel") _ <- newTask("Meet Tina Fey") _ <- completeTask("Go to scala days") tsks <- getTasks(Map.empty) } yield tsks

Page 52: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

val todosExpanded: Free[Todo, Map[String, Boolean]] = FlatMap( Suspend(NewTask("Go to Curry On")), (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)) ) ) ) )

Page 53: Curry On 2016 - Why the Free Monad isn't Free

result

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

1

2 3

fn:

value* 2

I'm not free :(

2

4 6

Page 54: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

1

2 3

fn:

value* 2

1*2

2*2 3*2result

I'm free!

Page 55: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

- Monoids, Functors & Monads

- How to be “Free”

- Why & Why Not “Free”

- Alternatives

- Real World Applications

$

@kelleyrobinson

Page 56: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

What's the point?

• Defer side effects

• Multiple interpreters

• Stack safety

@kelleyrobinson

Page 57: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

(1 to 1000).flatMap { i => doSomething(i).flatMap { j => doSomethingElse(j).flatMap { k => doAnotherThing(k).map { l => ...

Page 58: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

“Let’s just trampoline it and add the Free Monad”

@kelleyrobinson

Page 59: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

Trampolining Express it in a loop

@kelleyrobinson

Page 60: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

The Free Monad uses heap instead of using stack.

@kelleyrobinson

Page 61: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

not free

result

Page 62: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

free

result

Page 63: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

val todosExpanded: Free[Todo, Map[String, Boolean]] = FlatMap( Suspend(NewTask("Go to Curry On")), (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)) ) ) ) )

Page 64: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

Evaluating Use a loop

Page 65: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

def runFree[F[_], G[_], A]

(f: Free[F, A])

(transform: ContextTransformer[F, G])

(implicit G: Monad[G]): G[A]

Page 66: Curry On 2016 - Why the Free Monad isn't Free

@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

Page 67: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

// or 'NaturalTransformation'trait FunctorTransformer[F[_], G[_]] { def apply[A](f: F[A]): G[A] }

Page 68: Curry On 2016 - Why the Free Monad isn't Free

@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

Page 69: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

tailThis(f) match { case Return(a) => ... case Suspend(fa) => transform(fa) case FlatMap(Suspend(fa), fn) => ... transform(fa) ... case _ => ... }

https://github.com/robinske/monad-examples

Page 70: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

def runLoop(...) = { 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") }

Page 71: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

Evaluating

Applies transformation on `Suspend`

Trampolining for stack safety

Page 72: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

trait FunctorTransformer[F[_], G[_]] { def apply[A](f: F[A]): G[A] }

Page 73: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

type Id[A] = A

case class TestInterpreter(var model: Map[String, Boolean]) extends FunctorTransformer[Todo, Id] { def apply[A](a: Todo[A]): Id[A]

}

Page 74: Curry On 2016 - Why the Free Monad isn't Free

@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] }

Page 75: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

it("should evaluate todos") { val result = runFree(todos)(TestInterpreter(Map.empty)) val expected: Map[String, Boolean] = Map( "Go to Curry On" -> true, "Write a novel" -> false, "Meet Tina Fey" -> false ) result shouldBe expected}

Page 76: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

case object ActionTestInterpreter extends FunctorTransformer[Todo, Id] { var actions: List[Todo[String]] = List.empty def apply[A](a: Todo[A]): Id[A]

}

Page 77: Curry On 2016 - Why the Free Monad isn't Free

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

Page 78: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

it("should evaluate todos actions in order") { runFree(todos)(ActionTestInterpreter) val expected: List[Todo[String]] = List( NewTask("Go to Curry On"), NewTask("Write a novel"), NewTask("Meet Tina Fey"), CompleteTask("Go to scala days"), GetTasks("") ) ActionTestInterpreter.actions shouldBe expected }

Page 79: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

Defining multiple interpreters allows you to test side-effecting code without

using testing mocks.

Page 80: Curry On 2016 - Why the Free Monad isn't Free

@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) => ... } }

Page 81: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

Justifications

• Defer side effects

• Multiple interpreters

• Stack safety

Page 82: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

#BlueSkyScala The path to learning is broken

@kelleyrobinson

Credit: Jessica Kerr

Page 83: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

"Programming isn't math, and sometimes we hoist vocabulary

that confers similar meanings" - Marius Eriksen

https://github.com/twitter/bijection/issues/41#issuecomment-12051961

Page 84: Curry On 2016 - Why the Free Monad isn't Free
Page 85: Curry On 2016 - Why the Free Monad isn't Free

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

Page 86: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

- Monoids, Functors & Monads

- How to be “Free”

- Why & Why Not “Free”

- Alternatives

- Real World Applications

$

@kelleyrobinson

Page 87: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

Know your domain

Page 88: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

Functional Spectrum Where does your team fall?

Java Haskell

Page 89: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

Functional Spectrum Where does your team fall?

Java Haskell

Page 90: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

Alternatives for maintaining stack safety

Page 91: Curry On 2016 - Why the Free Monad isn't Free

@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)}

Page 92: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

Alternatives for managing side effects

Page 93: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

import java.sql.ResultSetcase class Person(name: String, age: Int)def getPerson(rs: ResultSet): Person = { val name = rs.getString(1) val age = rs.getInt(2) Person(name, age)}

Page 94: Curry On 2016 - Why the Free Monad isn't Free

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

Page 95: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

- Monoids, Functors & Monads

- How to be “Free”

- Why & Why Not “Free”

- Alternatives

- Real World Applications

$

@kelleyrobinson

Page 96: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

Language libs i.e. Scala Cats Lightweight, modular, and extensible library for functional programming. http://typelevel.org/cats/

@kelleyrobinson

Built in? Some languages (Haskell) have built-in support https://wiki.haskell.org/Monad

Page 97: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN'T FREE

Examples

• Doobie

• scalaz.concurrent.Task

@kelleyrobinson

https://github.com/tpolecat/doobie

Page 98: Curry On 2016 - Why the Free Monad isn't Free

@kelleyrobinson

import scalaz.concurrent.Task

val tasks = messages.map(m => Task { processSQSMessage(conf, m)}) Task.gatherUnordered(tasks).attemptRun match { case -\/(exp) => error(s"Failed processing") case _ => ()}

Page 99: Curry On 2016 - Why the Free Monad isn't Free

@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] { ... } }

Page 100: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

@kelleyrobinson

My experience... ...what happened?

Page 101: Curry On 2016 - Why the Free Monad isn't Free

WHY THE FREE MONAD ISN’T FREE

- Know your domain

- Use clean abstractions

- Share knowledge

$

@kelleyrobinson

Page 102: Curry On 2016 - Why the Free Monad isn't Free

Thank You! @kelleyrobinson

[email protected]

Page 103: Curry On 2016 - Why the Free Monad isn't Free

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