Upgrade to Pro — share decks privately, control downloads, hide ads and more …

OptimusPrimeT (cats edition)

OptimusPrimeT (cats edition)

Demo code: https://github.com/larsrh/flatmap2015

Everybody knows monads by now, so a talk about monads would hardly be worthwhile. Let's take it to the next level: monad transformers. We'll learn what they are, how they naturally emerge in your code base and how to make good use of them in Scala – and maybe even how to create your own.

A1216674d5c9747bcdcc716872439137?s=128

Lars Hupel

April 27, 2015
Tweet

More Decks by Lars Hupel

Other Decks in Programming

Transcript

  1. OptimusPrimeT Lars Hupel April 27th, 2015

  2. None
  3. None
  4. (A ⊗ B) ⊗ TC αA,B,TC  tA⊗B,C // T((A

    ⊗ B) ⊗ C) T(αA,B,C)  A ⊗ (B ⊗ TC) A⊗tB,C // A ⊗ T(B ⊗ C) tA,B⊗C // T(A ⊗ (B ⊗ C))
  5. None
  6. None
  7. Agenda 1 Functors, Applicatives, Monads 2 Composition of Functors 3

    Monad Transformers 7
  8. Functors, Applicatives, Monads Everyone knows monads, right? But: there’s more.

    8
  9. If all you have are monads ... Monads have lots

    of use cases: ▶ error handling ▶ parser combinators ▶ value-oriented parallelism ▶ ... 9
  10. Limitations of monads Code using monads has both mathematical and

    practical limitations 10
  11. Demo1

  12. Functors from the ground up Functors are about transforming data

    scala> List(1, 2, 3).map(x => x + 1) List(2, 3, 4) scala> Some(1).map(x => x + 1) Some(2) scala> Future { 1 }.map(x => x + 1) // something resembling 2 12
  13. Functors from the ground up Functors are about transforming data

    scala> List(1, 2, 3).map(x => x + 1) List(2, 3, 4) scala> Some(1).map(x => x + 1) Some(2) scala> Future { 1 }.map(x => x + 1) // something resembling 2 12
  14. The Functor class cats offers a generalization of that pattern

    trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } 13
  15. More power: Applicatives Applicatives are about transforming independent pieces of

    data scala> Applicative[List]. map2(List(1, 2), List(3, 4))(_ -> _) List((1, 3), (1, 4), (2, 3), (2, 4)) 14
  16. The Applicative class trait Applicative[F[_]] extends Functor[F] { def map2[A,

    B, C](fa: F[A], fb: F[B]) (f: (A, B) => C): F[C] } 15
  17. Even more power: Monads Monads are about transforming dependent pieces

    of data def fileRequest(user: User, file: Path): Future[Int] = for { token <- db.getAccessToken(user) input <- db.readFile(token, file) _ <- HTTP.sendHeader(HTTP.OK) written <- HTTP.sendBody(input) } yield written 16
  18. The Monad class trait Monad[F[_]] extends Applicative[F] { def flatMap[A,

    B](fa: F[A])(f: A => F[B]): F[B] } 17
  19. The Monad class trait Monad[F[_]] extends Applicative[F] { def flatMap[A,

    B](fa: F[A])(f: A => F[B]): F[B] def map2[A, B, C](fa: F[A], fb: F[B]) (f: (A, B) => C): F[C] = ??? } 17
  20. The Monad class trait Monad[F[_]] extends Applicative[F] { def flatMap[A,

    B](fa: F[A])(f: A => F[B]): F[B] def map2[A, B, C](fa: F[A], fb: F[B]) (f: (A, B) => C): F[C] = flatMap(fa) { a => flatMap(fb) { b => f(a, b) } } } 17
  21. Monad vs Applicative revisited Demo2 18

  22. Agenda 1 Functors, Applicatives, Monads 2 Composition of Functors 3

    Monad Transformers 19
  23. Programming is ... Abstracting! But: non-composable abstractions are useless 20

  24. Composing functors Input def intToString(x: Int): String val xss: List[List[Int]]

    Output val yss: List[List[String]] = ??? 21
  25. Demo3

  26. But what about monads? Surely we can also compose monads.

    23
  27. But what about monads? Surely we can also compose monads.

    Except we can’t 23
  28. But what about monads? Surely we can also compose monads.

    Except we can’t (in general) 23
  29. Agenda 1 Functors, Applicatives, Monads 2 Composition of Functors 3

    Monad Transformers 24
  30. Composing monads Our Tools // Monad[F] def flatMap[A, B](fa: F[A])(f:

    A => F[B]): F[B] // Monad[G] def flatMap[A, B](fa: G[A])(f: A => G[B]): G[B] Our Goal def flatMap[A, B](fga: F[G[A]]) (f: A => F[G[B]]): F[G[B]] 25
  31. Computer Science Interlude The Halting Problem It is undecidable whether

    a program will terminate on a given input. 26
  32. Computer Science Interlude The Halting Problem It is undecidable whether

    a program will terminate on a given input. ... defeated? Yet there are programming languages which only accept terminating programs. 26
  33. Composing particular monads Our Tools (refined) // Monad[F] def flatMap[A,

    B](fa: F[A])(f: A => F[B]): F[B] Our Goal (refined) def flatMapForOption[A, B] (foa: F[Option[A]]) (f: A => F[Option[B]]): F[Option[B]] 27
  34. Demo4

  35. When do monads transform? It’s difficult. 29

  36. Recap ▶ Monads are awesome, but often too powerful. ▶

    Functors compose. ▶ Applicatives compose. ▶ Monads do not compose in general. ▶ Specific monads do compose. ▶ That actually comes up very often. 30
  37. None
  38. None
  39. The End @larsr h larsrh.github.io typelevel.org/blog