61
Drinking the free kool-aid Drinking the free kool-aid David Hoyt David Hoyt

Drinking the free kool-aid

Embed Size (px)

Citation preview

Page 1: Drinking the free kool-aid

Drinking the free kool-aidDrinking the free kool-aid

David HoytDavid Hoyt

Page 2: Drinking the free kool-aid

AcknowledgmentsAcknowledgmentsFunctional Programming in Scala

Compositional Application Architecture WithReasonably Priced Monads

Page 3: Drinking the free kool-aid

What's the problem?What's the problem?

Page 4: Drinking the free kool-aid

You're not aloneYou're not aloneTook me a while to understandTook me a while to understand

Single pass wasn't enoughSingle pass wasn't enough

Page 5: Drinking the free kool-aid

YawnYawn

Page 6: Drinking the free kool-aid

for { _ <- tell("Twitter handle(s):", "tpolecat") handles <- ask("tpolecat") tweets <- getTweets(handles.split(',')) done <- displayTweets(tweets)} yield done

Given this program:Given this program:

Page 7: Drinking the free kool-aid

Let's run it like this...Let's run it like this...

Page 8: Drinking the free kool-aid

No changes to the No changes to the original program!original program!

Page 9: Drinking the free kool-aid

Another tool in your utility beltUse judiciously

The free monadThe free monad

Page 10: Drinking the free kool-aid

Why do I care?Why do I care?Purity of abstraction

Reusable definitions

Defer effects

Page 11: Drinking the free kool-aid

Services services servicesServices services services

Page 12: Drinking the free kool-aid

Wheel of doomWheel of doom®?

Page 13: Drinking the free kool-aid

WTFWTF

Page 14: Drinking the free kool-aid

AgendaAgenda1. Fundamentals

2. Code

3. Intuition

4. Code

5. Wrap-up

Page 15: Drinking the free kool-aid

Design patterns andDesign patterns andmathematical rigormathematical rigor

Page 16: Drinking the free kool-aid

trait NaturalTransformation[F[_], G[_]] { def apply[A](given: F[A]): G[A]}

type ~>[F[_], G[_]] = NaturalTransformation[F, G]

Natural transformationNatural transformation

Page 17: Drinking the free kool-aid

class Option[A]class List[A]

object optionToList extends (Option ~> List) { def apply[A](given: Option[A]): List[A] = given.toList}

Option to ListOption to List

Page 18: Drinking the free kool-aid

trait Monoid[A] { def zero: A def append(a1: A, a2: => A): A}

MonoidMonoid

Page 19: Drinking the free kool-aid

object stringConcatenation extends Monoid[String] { val zero: String = ""

def append(a1: String, a2: => String): String = a1 + a2}

String concatenationString concatenation

Page 20: Drinking the free kool-aid

A, A, A, A, A, A

Free monoidFree monoidStuff this next to that.Stuff this next to that.

Kind of looks like a List.Kind of looks like a List.

Page 21: Drinking the free kool-aid

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

FunctorFunctor

Page 22: Drinking the free kool-aid

(F[A], (A => A, A => B, B => C))

Free functorFree functoraka the CoYonedaaka the CoYoneda

Page 23: Drinking the free kool-aid

Seems uselessSeems uselessYup.Yup.

Except...Except...

Page 24: Drinking the free kool-aid

trait Monad[M[_]] { def pure[A](given: A): M[A] def flatMap[A, B](given: M[A])(fn: A => M[B]): M[B]}

trait Monad[M[_]] extends Functor[M] { def pure[A](given: A): M[A] def flatMap[A, B](given: M[A])(fn: A => M[B]): M[B]

override def map[A, B](given: M[A])(fn: A => B): M[B] = flatMap(given)(a => pure(fn(a)))}

MonadMonad

Page 25: Drinking the free kool-aid

val result: Future[Int] = for { value1 <- Future(1) value2 <- Future(2) } yield value1 + value2

Sequencing computationSequencing computation

Page 26: Drinking the free kool-aid

type Id[A] = A

implicit object Identity extends Monad[Id] { def pure[A](given: A): Id[A] = given

def map[A, B](given: Id[A])(fn: A => B): Id[B] = fn(given)

def flatMap[A, B](given: Id[A])(fn: A => Id[B]): Id[B] = fn(given)}

Identity monadIdentity monad

Page 27: Drinking the free kool-aid

Repeat after me...Repeat after me...Free monad = AST + interpreterFree monad = AST + interpreter

Page 28: Drinking the free kool-aid

Abstract Syntax TreesAbstract Syntax TreesExpresses computation as dataExpresses computation as data

The "what"

Page 29: Drinking the free kool-aid

InterpreterInterpreterGives meaning to the dataGives meaning to the data

The "how"

Page 30: Drinking the free kool-aid

I have a math problemI have a math problem(there are several interpretations of that statement...)

(yes, I mean all of them at once...)

(cue the IDE already!)

Page 31: Drinking the free kool-aid

What's 1 + 2?What's 1 + 2?(why didn't you cut to the IDE?!)

(don't let the audience see this!)

Page 32: Drinking the free kool-aid

You did what with that?You did what with that?That's right, I interpreted the sh** out of that. (NSFW?)

Page 33: Drinking the free kool-aid

sealed trait Free[F[_], A]

Free MonadFree Monad

Page 34: Drinking the free kool-aid

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

case class FlatMap[F[_], A, B](given: Free[F, A], fn: A => Free[F, B]) extends Free[F, B]

AST for monadsAST for monads

Page 35: Drinking the free kool-aid

sealed trait Free[F[_], A] { self => def map[B](fn: A => B): Free[F, B] = flatMap(a => Return(fn(a)))

def flatMap[B](fn: A => Free[F, B]): Free[F, B] = FlatMap(self, (a: A) => fn(a))}

Free MonadFree Monad

Page 36: Drinking the free kool-aid

Free MonadFree Monad

sealed trait Context[A]

val result: Free[Context, String] = for { hope <- Return[Context, String]("hope") it <- Return[Context, String]("it") works <- Return[Context, String]("works") } yield s"$hope $it $works"

Page 37: Drinking the free kool-aid

Free MonadFree Monad

sealed trait Context[A]

val result: Free[Context, String] = Return[Context, String]("hope") flatMap { hope => Return[Context, String]("it") flatMap { it => Return[Context, String]("works") map { works => s"$hope $it $works" } } }

Page 38: Drinking the free kool-aid

Which is really...Which is really...

FlatMap(Return("hope"), hope => FlatMap(Return("it"), it => FlatMap(Return("works"), works => Return(s"$hope $it $works"))))

Page 39: Drinking the free kool-aid

def join[A](ffa: F[F[A]]): F[A] = ???

Unable to joinUnable to join

Page 40: Drinking the free kool-aid

Fs all the way downFs all the way down

F[F[F[F[F[F[F[F[F[F[F[F[F[F[F[F[A]]]]]]]]]]]]]]]]

Page 41: Drinking the free kool-aid

So what you're saying is...So what you're saying is...We have a monad for monadsWe have a monad for monads

but it doesn't do monad-y things...but it doesn't do monad-y things...

Page 42: Drinking the free kool-aid

Now you're getting it!Now you're getting it!

Page 43: Drinking the free kool-aid

Shedding layersShedding layers

def runFree[F[_], G[_], A](given: Free[F, A]) (nat: F ~> G) (implicit G: Monad[G]): G[A]

Page 44: Drinking the free kool-aid

How is it "free"?How is it "free"?

If F is a functor, we get amonad without havingto do any extra work!

sealed trait Free[F[_], A]

Page 45: Drinking the free kool-aid

Free as in beer?Free as in beer?Free in this context means generated freely in the sense that [afoo] itself doesn’t need to have any [foo] structure of its own.

- Functional Programming in Scala

Page 46: Drinking the free kool-aid

Did he really just say "free foo"?Did he really just say "free foo"?Yes.Yes.

Page 47: Drinking the free kool-aid

Check it outCheck it out

Page 48: Drinking the free kool-aid

Repeat after me...Repeat after me...Free monad = AST + interpreterFree monad = AST + interpreter

Page 49: Drinking the free kool-aid

Can I compose different Fs?Can I compose different Fs?(Great question! You read my mind!)

Page 50: Drinking the free kool-aid

What I mean is...What I mean is...trait Foo[A]trait Bar[A]

val foo: Free[Foo, A] = ???val bar: Free[Bar, A] = ???

for { _ <- foo _ <- bar} yield ()

Page 51: Drinking the free kool-aid

NoNo

Page 52: Drinking the free kool-aid

Well, yes!Well, yes!

Page 53: Drinking the free kool-aid

What?!What?!

Page 54: Drinking the free kool-aid

Coproducts to the rescue!Coproducts to the rescue!(honorable mention: monad transformers)

case class Coproduct[F[_], G[_], A]()

Page 55: Drinking the free kool-aid

Read the bookRead the book by Wouter SwierstraData types à la carte

Page 56: Drinking the free kool-aid

Watch the movieWatch the movieCompositional Application Architecture

With Reasonably Priced Monads

Page 57: Drinking the free kool-aid

throw new NotImplementedError()throw new NotImplementedError()Trampolining

Page 58: Drinking the free kool-aid

Honorable mentionsHonorable mentionsCats

Scalaz

Page 60: Drinking the free kool-aid

Where's the source?Where's the source?

https://github.com/davidhoyt/kool-aid

Page 61: Drinking the free kool-aid

LegalLegalxkcd