SlideShare une entreprise Scribd logo
1  sur  46
Télécharger pour lire hors ligne
Classy Monad Transformers (Stop Eff’ing)
Sukant Hajra / @shajra
March 24, 2017
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 1 / 46
Goals
introduce monad transformers
illustrate ergonomics in Scala
recommend a usage
begin comparison with alternatives
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 2 / 46
Quick mention
Figure 1: My Employer
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 3 / 46
Materials
This presentation and all code is
at github.com/shajra/shajra-presentations/tree/master/scala-mtl
compiler-checked by Rob Norris’s sbt-tut plugin.
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 4 / 46
In lieu of time
Assuming knowledge of
Scala implicits
type classes
for-yield sugar w.r.t. Monad.
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 5 / 46
Monads, Explicitly
1trait Monad[M[_]] {
3def pure[A](a: A): M[A]
5def flatMap[A, B](ma: M[A])(f: A => M[B]): M[B] =
6flatten(map(ma)(f))
8def flatten[A](mma: M[M[A]]): M[A] =
9flatMap(mma)(identity)
11def map[A, B](ma: M[A])(f: A => B): M[B] =
12flatMap(ma)(f andThen pure)
14}
Note: the Monad type class has three laws
very important, but elided for time
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 6 / 46
Monad syntax with implicits
For convenience (e.g. with for-yield)
1implicit class OpsA[A](a: A) {
3def pure[M[_]](implicit M: Monad[M]): M[A] =
4M pure a
6}
8implicit class
9MonadOps[M[_], A](ma: M[A])(implicit M: Monad[M]) {
11def map[B](f: A => B): M[B] =
12M.map(ma)(f)
14def flatMap[B](f: A => M[B]): M[B] =
15M.flatMap(ma)(f)
17}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 7 / 46
Towards Transformers
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 8 / 46
Where people come from
Enterprise Java
1trait DbConn; trait MetricsConn
3class UsersDao @Inject() (db: DbConn)
5class InsightsDao @Inject()
6(db: DbConn, metrics: MetricsConn)
8class App @Inject() (users: UsersDao, insights: InsightsDao)
Complaints
no compile-time safety
lacks composition with other FP practices
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 9 / 46
A first response
Have you tried passing a parameter to a function?
1trait DbConn; trait MetricsConn
3case class User(name: String)
4case class Insight(desc: String)
6def newUser(db: DbConn)(name: String): User = ???
8def getInsight
9(db: DbConn, metrics: MetricsConn)(user: User)
10: Insight = ???
12def runApp(db: DbConn, metrics: MetricsConn): Unit = ???
Observations
safer (no runtime reflection)
feels like “manual” dependency injection
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 10 / 46
A second response
Passing a parameter is just the “reader” monad
1case class Reader[R, A](run: R => A)
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 11 / 46
A second response
Reader’s monad instance
1implicit def readerMonad[R]: Monad[Reader[R, ?]] =
2new Monad[Reader[R, ?]] {
4def pure[A](a: A): Reader[R, A] =
5Reader { _ => a }
7override def flatMap[A, B]
8(ra: Reader[R, A])(f: A => Reader[R, B])
9: Reader[R, B] =
10Reader { r => f(ra run r) run r }
12}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 12 / 46
A second response
1trait DbConfig; trait MetricsConfig
3case class AppConfig(db: DbConfig, metrics: MetricsConfig)
5def newUser(name: String): Reader[AppConfig, User] = ???
7def getInsight(user: User): Reader[AppConfig, Insight] = ???
9def showInsight
10(insight: Insight): Reader[AppConfig, Unit] = ???
12def app: Reader[AppConfig, Unit] =
13for {
14u <- newUser("Sukant")
15i <- getInsight(u)
16_ <- showInsight(i)
17} yield ()
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 13 / 46
A second response
Benefits
Plumbing is hidden a little.
We’re getting some composition.
Complaints
A global config is anti-modular.
Side-effects! Is this even FP?
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 14 / 46
Effect-tracking types
Naive implementation for presentation (stack unsafe)
1class IO[A](a: => A) {
2def unsafeRun: A = a
3}
5object IO { def apply[A](a: => A) = new IO(a) }
7implicit def ioMonad: Monad[IO] =
8new Monad[IO] {
9def pure[A](a: A): IO[A] = IO(a)
10override def flatMap[A, B]
11(ioa: IO[A])(f: A => IO[B]): IO[B] =
12IO(f(ioa.unsafeRun).unsafeRun)
13}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 15 / 46
Effect-tracking types
No side-effects while composing
1def getTime: IO[Long] = IO { System.currentTimeMillis }
2def printOut[A](a: A): IO[Unit] = IO { println(a) }
4def sillyIO: IO[Unit] =
5for {
6t <- getTime
7_ <- printOut(t)
8_ <- printOut(t)
9} yield ()
Run at the “end of the world”
1scala> sillyIO.unsafeRun
21490293856842
31490293856842
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 16 / 46
Thus far we have
Two monads
Reader passes in a parameters
IO tracks an effect
Is composing them useful?
Reader[IO[A]]
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 17 / 46
Let’s compose our monads
But in general, monads don’t compose
1case class Compose[F[_], G[_], A](fga: F[G[A]])
3def impossible[F[_] : Monad, G[_] : Monad]
4: Monad[Compose[F, G, ?]] = ???
Even if we can flatten F[F[A]] and G[G[A]]
It’s hard to flatten F[G[F[G[A]]]].
Can we compose IO and Reader specifically?
Yes, that’s exactly what monad transformers do.
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 18 / 46
Many monads have respective transformers
Reader’s transformer — ReaderT
1case class ReaderT[R, M[_], A](run: R => M[A])
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 19 / 46
ReaderT’s monad instance
Depends on inner type’s monad instance
1implicit def readerTMonad[R, M[_]]
2(implicit M: Monad[M]): Monad[ReaderT[R, M, ?]] =
4new Monad[ReaderT[R, M, ?]] {
6def pure[A](a: A): ReaderT[R, M, A] =
7ReaderT { _ => M.pure(a) }
9override def flatMap[A, B]
10(ma: ReaderT[R, M, A])(f: A => ReaderT[R, M, B])
11: ReaderT[R, M, B] =
12ReaderT { r => M.flatMap(ma run r) { f(_) run r } }
14}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 20 / 46
We can create “stacked” monads
Composing a monad stack
1type Stack[A] = ReaderT[Int, IO, A]
3val concretelyBuilt: Stack[(String, Int, Long)] =
4for {
5c <- "hi".pure[Stack]
6r <- ReaderT { (r: Int) => r.pure[IO] } // ugly
7t <- ReaderT { (_: Int) => getTime } // ugly
8} yield (c, r, t)
Running a monad stack
1scala> concretelyBuilt.run(1).unsafeRun
2res16: (String, Int, Long) = (hi,1,1490293857180)
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 21 / 46
A useful typeclass for readers
1trait MonadReader[R, M[_]] {
3def monad: Monad[M]
5def ask: M[R]
6def local[A](ma: M[A])(f: R => R): M[A]
8}
10object MonadReader {
11def ask[M[_], R](implicit MR: MonadReader[R, M]): M[R] =
12MR.ask
13}
Note: the MonadReader type class has laws
very important, but elided for time
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 22 / 46
Creating MonadReader for ReaderT
1implicit def readerTMonadReader[R, M[_]]
2(implicit M: Monad[M])
3: MonadReader[R, ReaderT[R, M, ?]] =
4new MonadReader[R, ReaderT[R, M, ?]] {
6val monad = readerTMonad(M)
8def ask: ReaderT[R, M, R] = ReaderT { _.pure[M] }
10def local[A]
11(ma: ReaderT[R, M, A])(f: R => R): ReaderT[R, M, A] =
12ReaderT { ma run f(_) }
14}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 23 / 46
Using stacks with parametric polymorphism
Stack not specified, only constrained
1def abstractlyBuilt[M[_] : Monad : MonadReader[Int, ?[_]]]
2: M[(String, Int)] =
3for {
4c <- "hi".pure[M]
5r <- MonadReader.ask[M, Int]
7// can't do this yet
8// t <- ReaderT { (_: Int) => getTime }
10// nicer syntax would be
11// getTime.liftBase[M]
13} yield (c, r)
Stack specified when run
1scala> abstractlyBuilt[Stack].run(1).unsafeRun
2res18: (String, Int) = (hi,1)
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 24 / 46
One more useful lift
For lifting your base monad
1trait MonadBase[B[_], M[_]] {
3def monadBase: Monad[B]
4def monad: Monad[M]
6def liftBase[A](base: B[A]): M[A]
8}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 25 / 46
A lift behind the scenes
People used to complain about this
1trait MonadTrans[T[_[_], _]] {
2def liftT[G[_] : Monad, A](a: G[A]): T[G, A]
3}
But now it can be internal plumbing
Don’t lift too much!
With the SI-2712 fix, you don’t have to
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 26 / 46
Many other transformers
Transformer Underlying Type class
IdentityT[M[_], A] M[A]
ReaderT[S, M[_], A] R =>M[A] MonadReader[R, M[_]]
StateT[S, M[_], A] S =>M[(S, A)] MonadState[S, M[_]]
OptionT[M[_], A] M[Option[A]] MonadOption[E, M[_]]
EitherT[E, M[_], A] M[Either[E,A]] MonadError[E, M[_]]
ContT[M[_], A] (A =>M[R])=>M[R] MonadCont[M[_]]
. . . . . . . . .
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 27 / 46
Some transformers commute effects
But we end up with O(n2
) to support them
1implicit def readerTMonadState[R, S, M[_]]
2(implicit MS: MonadState[S, M])
3: MonadState[S, ReaderT[R, M, ?]] =
4??? // can be implemented lawfully
Not all transformers commute effects
1implicit def contTMonadError[R, E, M[_]]
2(implicit ME: MonadError[E, M])
3: MonadError[E, ContT[M, ?]] =
4??? // would break MonadError laws if implemented
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 28 / 46
What have we got thus far?
Improvements
separations of concerns (Reader from IO)
no side-effects
Remaining Complaint
still using a global configuration
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 29 / 46
Classy Monad Transformers Example
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 30 / 46
Setup
Using a fork of Aloïs Cochard’s “scato-style” Scalaz 8
1import scalaz.Prelude.Base._
Notable differences
minimal subtyping
SI-2712 fixed!
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 31 / 46
Some abstractions
Our configuration from before
1case class DbConfig()
2case class MetricsConfig()
3case class AppConfig(db: DbConfig, metrics: MetricsConfig)
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 32 / 46
Don’t use transformer class directly
App-level type classes
1trait MonadDb[M[_]] {
2def monadBase: MonadBase[IO, M]
3def dbConfig: M[DbConfig]
4}
6trait MonadMetrics[M[_]] {
7def monadBase: MonadBase[IO, M]
8def metricsConfig: M[MetricsConfig]
9}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 33 / 46
Scato-encoding isn’t perfect
Because we’re not subtyping
1trait AppHierarchy0 extends scalaz.BaseHierarchy {
2implicit def metricsMonadBase[M[_]]
3(implicit M: MonadMetrics[M]): MonadBase[IO, M] =
4M.monadBase
5}
7trait AppHierarchy1 extends AppHierarchy0 {
8implicit def dbMonadBase[M[_]]
9(implicit M: MonadDb[M]): MonadBase[IO, M] =
10M.monadBase
11}
13object AppHierarchy extends AppHierarchy1
14import AppHierarchy._
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 34 / 46
Make an “app” monad
Use whatever stack makes sense
1type AppStack[A] = ReaderT[AppConfig, IO, A]
2case class App[A](run: AppStack[A])
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 35 / 46
Make instances for the “app” monad
Haskell’s NewTypeDeriving would be nice here
1implicit val appInstances
2: MonadDb[App] with MonadMetrics[App] =
3new MonadDb[App] with MonadMetrics[App] {
4def monadBase =
5new MonadBaseClass[IO, App] with
6MonadClass.Template[App] with
7BindClass.Ap[App] {
8def pure[A](a: A): App[A] = App(a.pure[AppStack])
9def flatMap[A, B]
10(ma: App[A])(f: A => App[B]): App[B] =
11App(ma.run.flatMap(f andThen { _.run }))
12def liftBase[A](base: IO[A]) =
13App(base.liftBase[AppStack])
14def monadBase = Monad[IO]
15}
16def ask = MonadReader.ask[AppStack, AppConfig]
17def dbConfig = App(ask.map { _.db })
18def metricsConfig = App(ask.map { _.metrics })
19}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 36 / 46
Write agnostic computations
Low-level IO calls
1case class User(name: String)
2case class Insight(desc: String)
4def lowLevelMakeUser
5(db: DbConfig, name: String): IO[User] =
6User(name).pure[IO]
8def lowLevelGetInsight
9(db: DbConfig, metrics: MetricsConfig, user: User)
10: IO[Insight] =
11IO {
12val username = System getenv "USER"
13Insight(s"likes username: ${username}")
14}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 37 / 46
Write agnostic computations
Mid-level composition
1def makeUser[M[_]]
2(name: String)(implicit D: MonadDb[M]): M[User] =
3for {
4conf <- D.dbConfig
5user <- lowLevelMakeUser(conf, name).liftBase[M]
6} yield user
8def getInsight[M[_]]
9(user: User)(implicit D: MonadDb[M], M: MonadMetrics[M])
10: M[Insight] =
11for {
12db <- D.dbConfig
13metrics <- M.metricsConfig
14insight <-
15lowLevelGetInsight(db, metrics, user).liftBase[M]
16} yield insight
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 38 / 46
Write agnostic computations
One more mid-level
1def showInsight[M[_] : MonadBase[IO, ?[_]]]
2(user: User, insight: Insight): M[Unit] =
3IO{ println(s"${user.name} ${insight.desc}") }.liftBase[M]
Our final application
1def app[M[_] : MonadDb : MonadMetrics]: M[Unit] =
2for {
3user <- makeUser[M]("Sukant")
4insight <- getInsight[M](user)
5_ <- showInsight[M](user, insight)
6} yield ()
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 39 / 46
The end of the world
1val conf = AppConfig(DbConfig(), MetricsConfig())
1scala> app[App].run.run(conf).unsafeRun
2Sukant likes username: shajra
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 40 / 46
Effect Commutativity
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 41 / 46
We don’t have to specify a stack order
1type StateEff[F[_]] = MonadState[Int, F]
2type ErrorEff[F[_]] = MonadError[String, F]
4def tryMtl[F[_] : ErrorEff : StateEff] = {
5val attempt =
6for {
7_ <- 1.put[F]
8_ <- "oh noes".raiseError[F, Unit]
9} yield ()
10attempt.handleError(_ => ().pure[F])
11}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 42 / 46
Different stacks, different results
Stack Representation
StateT[Int, EitherT[String, Identity, ?], A] S =>M[Either[E, (S, A)]]
EitherT[String, StateT[Int, Identity, ?], A] S =>M[(S, Either[E, A])]
1type StackSE[A] =
2StateT[Int, EitherT[String, Identity, ?], A]
3type StackES[A] =
4EitherT[String, StateT[Int, Identity, ?], A]
1scala> tryMtl[StackSE].run(0).run.run
2res1: scalaz./[String,(Int, Unit)] = /-((0,()))
4scala> tryMtl[StackES].run.run(0).run
5res2: (Int, scalaz./[String,Unit]) = (1,/-(()))
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 43 / 46
Trying with Eff
1import cats.data._; import cats.syntax.all._
2import org.atnos.eff._; import org.atnos.eff.all._
3import org.atnos.eff.syntax.all._
5type StateEff[A] = State[Int, A]
6type ErrorEff[A] = Either[String, A]
8def tryEff[R]
9(implicit S: StateEff |= R , W: ErrorEff /= R)
10: Eff[R, Unit] = {
11val attempt: Eff[R, Unit] =
12for {
13_ <- put(1)
14_ <- left[R, String, Unit]("oh noes")
15} yield ()
16catchLeft[R, String, Unit](attempt) { _ =>
17().pure[Eff[R, ?]]
18}
19}
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 44 / 46
By default, interpretation locked in
1scala> type StackSE = Fx.fx2[StateEff, ErrorEff]
2defined type alias StackSE
4scala> type StackES = Fx.fx2[ErrorEff, StateEff]
5defined type alias StackES
7scala> tryEff[StackSE].runState(0).runEither.run
8res2: scala.util.Either[String,(Unit, Int)] = Right(((),1))
10scala> tryEff[StackSE].runEither.runState(0).run
11res3: (scala.util.Either[String,Unit], Int) = (Right(()),1)
13scala> tryEff[StackES].runState(0).runEither.run
14res4: scala.util.Either[String,(Unit, Int)] = Right(((),1))
16scala> tryEff[StackES].runEither.runState(0).run
17res5: (scala.util.Either[String,Unit], Int) = (Right(()),1)
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 45 / 46
Wrapping up
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 46 / 46

Contenu connexe

Tendances

Category Theory for Programmers
Category Theory for ProgrammersCategory Theory for Programmers
Category Theory for ProgrammersSantosh Rajan
 
Functional programming in kotlin with Arrow [Sunnytech 2018]
Functional programming in kotlin with Arrow [Sunnytech 2018]Functional programming in kotlin with Arrow [Sunnytech 2018]
Functional programming in kotlin with Arrow [Sunnytech 2018]Emmanuel Nhan
 
Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Philip Schwarz
 
Abstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsAbstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsPhilip Schwarz
 
Introduction to Category Theory for software engineers
Introduction to Category Theory for software engineersIntroduction to Category Theory for software engineers
Introduction to Category Theory for software engineersPranav Prakash
 
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
 
Sequence and Traverse - Part 3
Sequence and Traverse - Part 3Sequence and Traverse - Part 3
Sequence and Traverse - Part 3Philip Schwarz
 
19. Data Structures and Algorithm Complexity
19. Data Structures and Algorithm Complexity19. Data Structures and Algorithm Complexity
19. Data Structures and Algorithm ComplexityIntro C# Book
 
Whiteboarding Coding Challenges in Python
Whiteboarding Coding Challenges in PythonWhiteboarding Coding Challenges in Python
Whiteboarding Coding Challenges in PythonAndrew Ferlitsch
 
James Jesus Bermas on Crash Course on Python
James Jesus Bermas on Crash Course on PythonJames Jesus Bermas on Crash Course on Python
James Jesus Bermas on Crash Course on PythonCP-Union
 
Approximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming ApplicationsApproximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming ApplicationsDebasish Ghosh
 

Tendances (20)

Category Theory for Programmers
Category Theory for ProgrammersCategory Theory for Programmers
Category Theory for Programmers
 
Functional programming in kotlin with Arrow [Sunnytech 2018]
Functional programming in kotlin with Arrow [Sunnytech 2018]Functional programming in kotlin with Arrow [Sunnytech 2018]
Functional programming in kotlin with Arrow [Sunnytech 2018]
 
Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Sequence and Traverse - Part 2
Sequence and Traverse - Part 2
 
Abstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsAbstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generators
 
Introduction to Category Theory for software engineers
Introduction to Category Theory for software engineersIntroduction to Category Theory for software engineers
Introduction to Category Theory for software engineers
 
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
 
Sequence and Traverse - Part 3
Sequence and Traverse - Part 3Sequence and Traverse - Part 3
Sequence and Traverse - Part 3
 
19. Data Structures and Algorithm Complexity
19. Data Structures and Algorithm Complexity19. Data Structures and Algorithm Complexity
19. Data Structures and Algorithm Complexity
 
Functor Composition
Functor CompositionFunctor Composition
Functor Composition
 
JAVA OOP
JAVA OOPJAVA OOP
JAVA OOP
 
Templates
TemplatesTemplates
Templates
 
Functors
FunctorsFunctors
Functors
 
Whiteboarding Coding Challenges in Python
Whiteboarding Coding Challenges in PythonWhiteboarding Coding Challenges in Python
Whiteboarding Coding Challenges in Python
 
Python for data analysis
Python for data analysisPython for data analysis
Python for data analysis
 
Scala jargon cheatsheet
Scala jargon cheatsheetScala jargon cheatsheet
Scala jargon cheatsheet
 
James Jesus Bermas on Crash Course on Python
James Jesus Bermas on Crash Course on PythonJames Jesus Bermas on Crash Course on Python
James Jesus Bermas on Crash Course on Python
 
Monads do not Compose
Monads do not ComposeMonads do not Compose
Monads do not Compose
 
Approximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming ApplicationsApproximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming Applications
 
Java introduction
Java introductionJava introduction
Java introduction
 
Array ppt
Array pptArray ppt
Array ppt
 

En vedette

Understanding Your Metadata’s Journey
Understanding Your Metadata’s JourneyUnderstanding Your Metadata’s Journey
Understanding Your Metadata’s JourneyBookNet Canada
 
Memory Interoperability in Analytics and Machine Learning
Memory Interoperability in Analytics and Machine LearningMemory Interoperability in Analytics and Machine Learning
Memory Interoperability in Analytics and Machine LearningWes McKinney
 
Scala Validation with Functional Programming
Scala Validation with Functional ProgrammingScala Validation with Functional Programming
Scala Validation with Functional ProgrammingSukant Hajra
 
42.type: Literal-based Singleton types
42.type: Literal-based Singleton types42.type: Literal-based Singleton types
42.type: Literal-based Singleton typesGeorge Leontiev
 
Перший друкований публічний звіт СБУ за європейськими принципами, виданий за ...
Перший друкований публічний звіт СБУ за європейськими принципами, виданий за ...Перший друкований публічний звіт СБУ за європейськими принципами, виданий за ...
Перший друкований публічний звіт СБУ за європейськими принципами, виданий за ...Security Service of Ukraine
 
BFF Pattern in Action: SoundCloud’s Microservices
BFF Pattern in Action: SoundCloud’s MicroservicesBFF Pattern in Action: SoundCloud’s Microservices
BFF Pattern in Action: SoundCloud’s MicroservicesBora Tunca
 
Raising the Tides: Open Source Analytics for Data Science
Raising the Tides: Open Source Analytics for Data ScienceRaising the Tides: Open Source Analytics for Data Science
Raising the Tides: Open Source Analytics for Data ScienceWes McKinney
 
Reducing Boilerplate and Combining Effects: A Monad Transformer Example
Reducing Boilerplate and Combining Effects: A Monad Transformer ExampleReducing Boilerplate and Combining Effects: A Monad Transformer Example
Reducing Boilerplate and Combining Effects: A Monad Transformer ExampleConnie Chen
 
Make your programs Free
Make your programs FreeMake your programs Free
Make your programs FreePawel Szulc
 
Demystifying the Inner Workings of Amazon Keywords
Demystifying the Inner Workings of Amazon KeywordsDemystifying the Inner Workings of Amazon Keywords
Demystifying the Inner Workings of Amazon KeywordsBookNet Canada
 
11 flowers gifts which are perfect for allergy sufferers
11 flowers gifts which are perfect for allergy sufferers11 flowers gifts which are perfect for allergy sufferers
11 flowers gifts which are perfect for allergy sufferersCeline Wilson
 
Forum IA BX mars 2016 - Blade Runner
Forum IA BX mars 2016 - Blade RunnerForum IA BX mars 2016 - Blade Runner
Forum IA BX mars 2016 - Blade RunnerArmelle Gilliard
 
Dementia: An Overview
Dementia: An OverviewDementia: An Overview
Dementia: An OverviewIrene Ryan
 
Secret encoder ring
Secret encoder ringSecret encoder ring
Secret encoder ringToby Jaffey
 
Prise en charge du lymphoedème en hospitalisation complète
Prise en charge du lymphoedème en hospitalisation complètePrise en charge du lymphoedème en hospitalisation complète
Prise en charge du lymphoedème en hospitalisation complèteMaxime Blanc-Fontes
 

En vedette (20)

Understanding Your Metadata’s Journey
Understanding Your Metadata’s JourneyUnderstanding Your Metadata’s Journey
Understanding Your Metadata’s Journey
 
Memory Interoperability in Analytics and Machine Learning
Memory Interoperability in Analytics and Machine LearningMemory Interoperability in Analytics and Machine Learning
Memory Interoperability in Analytics and Machine Learning
 
Scala Validation with Functional Programming
Scala Validation with Functional ProgrammingScala Validation with Functional Programming
Scala Validation with Functional Programming
 
42.type: Literal-based Singleton types
42.type: Literal-based Singleton types42.type: Literal-based Singleton types
42.type: Literal-based Singleton types
 
Перший друкований публічний звіт СБУ за європейськими принципами, виданий за ...
Перший друкований публічний звіт СБУ за європейськими принципами, виданий за ...Перший друкований публічний звіт СБУ за європейськими принципами, виданий за ...
Перший друкований публічний звіт СБУ за європейськими принципами, виданий за ...
 
BFF Pattern in Action: SoundCloud’s Microservices
BFF Pattern in Action: SoundCloud’s MicroservicesBFF Pattern in Action: SoundCloud’s Microservices
BFF Pattern in Action: SoundCloud’s Microservices
 
Paper battery in IEEE format
Paper battery in IEEE formatPaper battery in IEEE format
Paper battery in IEEE format
 
Raising the Tides: Open Source Analytics for Data Science
Raising the Tides: Open Source Analytics for Data ScienceRaising the Tides: Open Source Analytics for Data Science
Raising the Tides: Open Source Analytics for Data Science
 
Reducing Boilerplate and Combining Effects: A Monad Transformer Example
Reducing Boilerplate and Combining Effects: A Monad Transformer ExampleReducing Boilerplate and Combining Effects: A Monad Transformer Example
Reducing Boilerplate and Combining Effects: A Monad Transformer Example
 
Ieee paper format
Ieee paper formatIeee paper format
Ieee paper format
 
Ieee slide format
Ieee slide formatIeee slide format
Ieee slide format
 
Make your programs Free
Make your programs FreeMake your programs Free
Make your programs Free
 
IEEE Presentation
IEEE PresentationIEEE Presentation
IEEE Presentation
 
Demystifying the Inner Workings of Amazon Keywords
Demystifying the Inner Workings of Amazon KeywordsDemystifying the Inner Workings of Amazon Keywords
Demystifying the Inner Workings of Amazon Keywords
 
11 flowers gifts which are perfect for allergy sufferers
11 flowers gifts which are perfect for allergy sufferers11 flowers gifts which are perfect for allergy sufferers
11 flowers gifts which are perfect for allergy sufferers
 
Forum IA BX mars 2016 - Blade Runner
Forum IA BX mars 2016 - Blade RunnerForum IA BX mars 2016 - Blade Runner
Forum IA BX mars 2016 - Blade Runner
 
The Crazy Cuban's Secret
The  Crazy Cuban's   SecretThe  Crazy Cuban's   Secret
The Crazy Cuban's Secret
 
Dementia: An Overview
Dementia: An OverviewDementia: An Overview
Dementia: An Overview
 
Secret encoder ring
Secret encoder ringSecret encoder ring
Secret encoder ring
 
Prise en charge du lymphoedème en hospitalisation complète
Prise en charge du lymphoedème en hospitalisation complètePrise en charge du lymphoedème en hospitalisation complète
Prise en charge du lymphoedème en hospitalisation complète
 

Similaire à Classy Guide to Monad Transformers in Scala

Advance Scala - Oleg Mürk
Advance Scala - Oleg MürkAdvance Scala - Oleg Mürk
Advance Scala - Oleg MürkPlanet OS
 
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021Peng Cheng
 
Kyo - Functional Scala 2023.pdf
Kyo - Functional Scala 2023.pdfKyo - Functional Scala 2023.pdf
Kyo - Functional Scala 2023.pdfFlavio W. Brasil
 
Scientific Computing with Python Webinar March 19: 3D Visualization with Mayavi
Scientific Computing with Python Webinar March 19: 3D Visualization with MayaviScientific Computing with Python Webinar March 19: 3D Visualization with Mayavi
Scientific Computing with Python Webinar March 19: 3D Visualization with MayaviEnthought, Inc.
 
Functional Reactive Programming on Android
Functional Reactive Programming on AndroidFunctional Reactive Programming on Android
Functional Reactive Programming on AndroidSam Lee
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Scalac
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Piotr Paradziński
 
Functional programming-advantages
Functional programming-advantagesFunctional programming-advantages
Functional programming-advantagesSergei Winitzki
 
Real world cats
Real world catsReal world cats
Real world catsIkhoon Eom
 
MATLAB-Cheat-Sheet-for-Data-Science_LondonSchoolofEconomics (1).pdf
MATLAB-Cheat-Sheet-for-Data-Science_LondonSchoolofEconomics (1).pdfMATLAB-Cheat-Sheet-for-Data-Science_LondonSchoolofEconomics (1).pdf
MATLAB-Cheat-Sheet-for-Data-Science_LondonSchoolofEconomics (1).pdfCentral university of Haryana
 
Three Dimensional Scaffold Direct Writer for Fabricating Fiber-Reinforced Mat...
Three Dimensional Scaffold Direct Writer for Fabricating Fiber-Reinforced Mat...Three Dimensional Scaffold Direct Writer for Fabricating Fiber-Reinforced Mat...
Three Dimensional Scaffold Direct Writer for Fabricating Fiber-Reinforced Mat...Rohan Rath
 
A practical work of matlab
A practical work of matlabA practical work of matlab
A practical work of matlabSalanSD
 
C++11: Feel the New Language
C++11: Feel the New LanguageC++11: Feel the New Language
C++11: Feel the New Languagemspline
 
Accelerating Random Forests in Scikit-Learn
Accelerating Random Forests in Scikit-LearnAccelerating Random Forests in Scikit-Learn
Accelerating Random Forests in Scikit-LearnGilles Louppe
 
Matlab for beginners, Introduction, signal processing
Matlab for beginners, Introduction, signal processingMatlab for beginners, Introduction, signal processing
Matlab for beginners, Introduction, signal processingDr. Manjunatha. P
 

Similaire à Classy Guide to Monad Transformers in Scala (20)

Advance Scala - Oleg Mürk
Advance Scala - Oleg MürkAdvance Scala - Oleg Mürk
Advance Scala - Oleg Mürk
 
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
 
Kyo - Functional Scala 2023.pdf
Kyo - Functional Scala 2023.pdfKyo - Functional Scala 2023.pdf
Kyo - Functional Scala 2023.pdf
 
Scientific Computing with Python Webinar March 19: 3D Visualization with Mayavi
Scientific Computing with Python Webinar March 19: 3D Visualization with MayaviScientific Computing with Python Webinar March 19: 3D Visualization with Mayavi
Scientific Computing with Python Webinar March 19: 3D Visualization with Mayavi
 
Functional Reactive Programming on Android
Functional Reactive Programming on AndroidFunctional Reactive Programming on Android
Functional Reactive Programming on Android
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
 
Practical cats
Practical catsPractical cats
Practical cats
 
Oops recap
Oops recapOops recap
Oops recap
 
Methods
MethodsMethods
Methods
 
Seeing Like Software
Seeing Like SoftwareSeeing Like Software
Seeing Like Software
 
Functional programming-advantages
Functional programming-advantagesFunctional programming-advantages
Functional programming-advantages
 
Real world cats
Real world catsReal world cats
Real world cats
 
MATLAB-Cheat-Sheet-for-Data-Science_LondonSchoolofEconomics (1).pdf
MATLAB-Cheat-Sheet-for-Data-Science_LondonSchoolofEconomics (1).pdfMATLAB-Cheat-Sheet-for-Data-Science_LondonSchoolofEconomics (1).pdf
MATLAB-Cheat-Sheet-for-Data-Science_LondonSchoolofEconomics (1).pdf
 
Three Dimensional Scaffold Direct Writer for Fabricating Fiber-Reinforced Mat...
Three Dimensional Scaffold Direct Writer for Fabricating Fiber-Reinforced Mat...Three Dimensional Scaffold Direct Writer for Fabricating Fiber-Reinforced Mat...
Three Dimensional Scaffold Direct Writer for Fabricating Fiber-Reinforced Mat...
 
A practical work of matlab
A practical work of matlabA practical work of matlab
A practical work of matlab
 
C++11: Feel the New Language
C++11: Feel the New LanguageC++11: Feel the New Language
C++11: Feel the New Language
 
Chap08
Chap08Chap08
Chap08
 
Accelerating Random Forests in Scikit-Learn
Accelerating Random Forests in Scikit-LearnAccelerating Random Forests in Scikit-Learn
Accelerating Random Forests in Scikit-Learn
 
Matlab for beginners, Introduction, signal processing
Matlab for beginners, Introduction, signal processingMatlab for beginners, Introduction, signal processing
Matlab for beginners, Introduction, signal processing
 

Dernier

BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noidabntitsolutionsrishis
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfIdiosysTechnologies1
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 

Dernier (20)

BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdf
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 

Classy Guide to Monad Transformers in Scala

  • 1. Classy Monad Transformers (Stop Eff’ing) Sukant Hajra / @shajra March 24, 2017 Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 1 / 46
  • 2. Goals introduce monad transformers illustrate ergonomics in Scala recommend a usage begin comparison with alternatives Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 2 / 46
  • 3. Quick mention Figure 1: My Employer Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 3 / 46
  • 4. Materials This presentation and all code is at github.com/shajra/shajra-presentations/tree/master/scala-mtl compiler-checked by Rob Norris’s sbt-tut plugin. Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 4 / 46
  • 5. In lieu of time Assuming knowledge of Scala implicits type classes for-yield sugar w.r.t. Monad. Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 5 / 46
  • 6. Monads, Explicitly 1trait Monad[M[_]] { 3def pure[A](a: A): M[A] 5def flatMap[A, B](ma: M[A])(f: A => M[B]): M[B] = 6flatten(map(ma)(f)) 8def flatten[A](mma: M[M[A]]): M[A] = 9flatMap(mma)(identity) 11def map[A, B](ma: M[A])(f: A => B): M[B] = 12flatMap(ma)(f andThen pure) 14} Note: the Monad type class has three laws very important, but elided for time Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 6 / 46
  • 7. Monad syntax with implicits For convenience (e.g. with for-yield) 1implicit class OpsA[A](a: A) { 3def pure[M[_]](implicit M: Monad[M]): M[A] = 4M pure a 6} 8implicit class 9MonadOps[M[_], A](ma: M[A])(implicit M: Monad[M]) { 11def map[B](f: A => B): M[B] = 12M.map(ma)(f) 14def flatMap[B](f: A => M[B]): M[B] = 15M.flatMap(ma)(f) 17} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 7 / 46
  • 8. Towards Transformers Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 8 / 46
  • 9. Where people come from Enterprise Java 1trait DbConn; trait MetricsConn 3class UsersDao @Inject() (db: DbConn) 5class InsightsDao @Inject() 6(db: DbConn, metrics: MetricsConn) 8class App @Inject() (users: UsersDao, insights: InsightsDao) Complaints no compile-time safety lacks composition with other FP practices Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 9 / 46
  • 10. A first response Have you tried passing a parameter to a function? 1trait DbConn; trait MetricsConn 3case class User(name: String) 4case class Insight(desc: String) 6def newUser(db: DbConn)(name: String): User = ??? 8def getInsight 9(db: DbConn, metrics: MetricsConn)(user: User) 10: Insight = ??? 12def runApp(db: DbConn, metrics: MetricsConn): Unit = ??? Observations safer (no runtime reflection) feels like “manual” dependency injection Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 10 / 46
  • 11. A second response Passing a parameter is just the “reader” monad 1case class Reader[R, A](run: R => A) Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 11 / 46
  • 12. A second response Reader’s monad instance 1implicit def readerMonad[R]: Monad[Reader[R, ?]] = 2new Monad[Reader[R, ?]] { 4def pure[A](a: A): Reader[R, A] = 5Reader { _ => a } 7override def flatMap[A, B] 8(ra: Reader[R, A])(f: A => Reader[R, B]) 9: Reader[R, B] = 10Reader { r => f(ra run r) run r } 12} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 12 / 46
  • 13. A second response 1trait DbConfig; trait MetricsConfig 3case class AppConfig(db: DbConfig, metrics: MetricsConfig) 5def newUser(name: String): Reader[AppConfig, User] = ??? 7def getInsight(user: User): Reader[AppConfig, Insight] = ??? 9def showInsight 10(insight: Insight): Reader[AppConfig, Unit] = ??? 12def app: Reader[AppConfig, Unit] = 13for { 14u <- newUser("Sukant") 15i <- getInsight(u) 16_ <- showInsight(i) 17} yield () Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 13 / 46
  • 14. A second response Benefits Plumbing is hidden a little. We’re getting some composition. Complaints A global config is anti-modular. Side-effects! Is this even FP? Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 14 / 46
  • 15. Effect-tracking types Naive implementation for presentation (stack unsafe) 1class IO[A](a: => A) { 2def unsafeRun: A = a 3} 5object IO { def apply[A](a: => A) = new IO(a) } 7implicit def ioMonad: Monad[IO] = 8new Monad[IO] { 9def pure[A](a: A): IO[A] = IO(a) 10override def flatMap[A, B] 11(ioa: IO[A])(f: A => IO[B]): IO[B] = 12IO(f(ioa.unsafeRun).unsafeRun) 13} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 15 / 46
  • 16. Effect-tracking types No side-effects while composing 1def getTime: IO[Long] = IO { System.currentTimeMillis } 2def printOut[A](a: A): IO[Unit] = IO { println(a) } 4def sillyIO: IO[Unit] = 5for { 6t <- getTime 7_ <- printOut(t) 8_ <- printOut(t) 9} yield () Run at the “end of the world” 1scala> sillyIO.unsafeRun 21490293856842 31490293856842 Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 16 / 46
  • 17. Thus far we have Two monads Reader passes in a parameters IO tracks an effect Is composing them useful? Reader[IO[A]] Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 17 / 46
  • 18. Let’s compose our monads But in general, monads don’t compose 1case class Compose[F[_], G[_], A](fga: F[G[A]]) 3def impossible[F[_] : Monad, G[_] : Monad] 4: Monad[Compose[F, G, ?]] = ??? Even if we can flatten F[F[A]] and G[G[A]] It’s hard to flatten F[G[F[G[A]]]]. Can we compose IO and Reader specifically? Yes, that’s exactly what monad transformers do. Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 18 / 46
  • 19. Many monads have respective transformers Reader’s transformer — ReaderT 1case class ReaderT[R, M[_], A](run: R => M[A]) Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 19 / 46
  • 20. ReaderT’s monad instance Depends on inner type’s monad instance 1implicit def readerTMonad[R, M[_]] 2(implicit M: Monad[M]): Monad[ReaderT[R, M, ?]] = 4new Monad[ReaderT[R, M, ?]] { 6def pure[A](a: A): ReaderT[R, M, A] = 7ReaderT { _ => M.pure(a) } 9override def flatMap[A, B] 10(ma: ReaderT[R, M, A])(f: A => ReaderT[R, M, B]) 11: ReaderT[R, M, B] = 12ReaderT { r => M.flatMap(ma run r) { f(_) run r } } 14} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 20 / 46
  • 21. We can create “stacked” monads Composing a monad stack 1type Stack[A] = ReaderT[Int, IO, A] 3val concretelyBuilt: Stack[(String, Int, Long)] = 4for { 5c <- "hi".pure[Stack] 6r <- ReaderT { (r: Int) => r.pure[IO] } // ugly 7t <- ReaderT { (_: Int) => getTime } // ugly 8} yield (c, r, t) Running a monad stack 1scala> concretelyBuilt.run(1).unsafeRun 2res16: (String, Int, Long) = (hi,1,1490293857180) Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 21 / 46
  • 22. A useful typeclass for readers 1trait MonadReader[R, M[_]] { 3def monad: Monad[M] 5def ask: M[R] 6def local[A](ma: M[A])(f: R => R): M[A] 8} 10object MonadReader { 11def ask[M[_], R](implicit MR: MonadReader[R, M]): M[R] = 12MR.ask 13} Note: the MonadReader type class has laws very important, but elided for time Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 22 / 46
  • 23. Creating MonadReader for ReaderT 1implicit def readerTMonadReader[R, M[_]] 2(implicit M: Monad[M]) 3: MonadReader[R, ReaderT[R, M, ?]] = 4new MonadReader[R, ReaderT[R, M, ?]] { 6val monad = readerTMonad(M) 8def ask: ReaderT[R, M, R] = ReaderT { _.pure[M] } 10def local[A] 11(ma: ReaderT[R, M, A])(f: R => R): ReaderT[R, M, A] = 12ReaderT { ma run f(_) } 14} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 23 / 46
  • 24. Using stacks with parametric polymorphism Stack not specified, only constrained 1def abstractlyBuilt[M[_] : Monad : MonadReader[Int, ?[_]]] 2: M[(String, Int)] = 3for { 4c <- "hi".pure[M] 5r <- MonadReader.ask[M, Int] 7// can't do this yet 8// t <- ReaderT { (_: Int) => getTime } 10// nicer syntax would be 11// getTime.liftBase[M] 13} yield (c, r) Stack specified when run 1scala> abstractlyBuilt[Stack].run(1).unsafeRun 2res18: (String, Int) = (hi,1) Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 24 / 46
  • 25. One more useful lift For lifting your base monad 1trait MonadBase[B[_], M[_]] { 3def monadBase: Monad[B] 4def monad: Monad[M] 6def liftBase[A](base: B[A]): M[A] 8} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 25 / 46
  • 26. A lift behind the scenes People used to complain about this 1trait MonadTrans[T[_[_], _]] { 2def liftT[G[_] : Monad, A](a: G[A]): T[G, A] 3} But now it can be internal plumbing Don’t lift too much! With the SI-2712 fix, you don’t have to Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 26 / 46
  • 27. Many other transformers Transformer Underlying Type class IdentityT[M[_], A] M[A] ReaderT[S, M[_], A] R =>M[A] MonadReader[R, M[_]] StateT[S, M[_], A] S =>M[(S, A)] MonadState[S, M[_]] OptionT[M[_], A] M[Option[A]] MonadOption[E, M[_]] EitherT[E, M[_], A] M[Either[E,A]] MonadError[E, M[_]] ContT[M[_], A] (A =>M[R])=>M[R] MonadCont[M[_]] . . . . . . . . . Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 27 / 46
  • 28. Some transformers commute effects But we end up with O(n2 ) to support them 1implicit def readerTMonadState[R, S, M[_]] 2(implicit MS: MonadState[S, M]) 3: MonadState[S, ReaderT[R, M, ?]] = 4??? // can be implemented lawfully Not all transformers commute effects 1implicit def contTMonadError[R, E, M[_]] 2(implicit ME: MonadError[E, M]) 3: MonadError[E, ContT[M, ?]] = 4??? // would break MonadError laws if implemented Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 28 / 46
  • 29. What have we got thus far? Improvements separations of concerns (Reader from IO) no side-effects Remaining Complaint still using a global configuration Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 29 / 46
  • 30. Classy Monad Transformers Example Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 30 / 46
  • 31. Setup Using a fork of Aloïs Cochard’s “scato-style” Scalaz 8 1import scalaz.Prelude.Base._ Notable differences minimal subtyping SI-2712 fixed! Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 31 / 46
  • 32. Some abstractions Our configuration from before 1case class DbConfig() 2case class MetricsConfig() 3case class AppConfig(db: DbConfig, metrics: MetricsConfig) Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 32 / 46
  • 33. Don’t use transformer class directly App-level type classes 1trait MonadDb[M[_]] { 2def monadBase: MonadBase[IO, M] 3def dbConfig: M[DbConfig] 4} 6trait MonadMetrics[M[_]] { 7def monadBase: MonadBase[IO, M] 8def metricsConfig: M[MetricsConfig] 9} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 33 / 46
  • 34. Scato-encoding isn’t perfect Because we’re not subtyping 1trait AppHierarchy0 extends scalaz.BaseHierarchy { 2implicit def metricsMonadBase[M[_]] 3(implicit M: MonadMetrics[M]): MonadBase[IO, M] = 4M.monadBase 5} 7trait AppHierarchy1 extends AppHierarchy0 { 8implicit def dbMonadBase[M[_]] 9(implicit M: MonadDb[M]): MonadBase[IO, M] = 10M.monadBase 11} 13object AppHierarchy extends AppHierarchy1 14import AppHierarchy._ Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 34 / 46
  • 35. Make an “app” monad Use whatever stack makes sense 1type AppStack[A] = ReaderT[AppConfig, IO, A] 2case class App[A](run: AppStack[A]) Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 35 / 46
  • 36. Make instances for the “app” monad Haskell’s NewTypeDeriving would be nice here 1implicit val appInstances 2: MonadDb[App] with MonadMetrics[App] = 3new MonadDb[App] with MonadMetrics[App] { 4def monadBase = 5new MonadBaseClass[IO, App] with 6MonadClass.Template[App] with 7BindClass.Ap[App] { 8def pure[A](a: A): App[A] = App(a.pure[AppStack]) 9def flatMap[A, B] 10(ma: App[A])(f: A => App[B]): App[B] = 11App(ma.run.flatMap(f andThen { _.run })) 12def liftBase[A](base: IO[A]) = 13App(base.liftBase[AppStack]) 14def monadBase = Monad[IO] 15} 16def ask = MonadReader.ask[AppStack, AppConfig] 17def dbConfig = App(ask.map { _.db }) 18def metricsConfig = App(ask.map { _.metrics }) 19} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 36 / 46
  • 37. Write agnostic computations Low-level IO calls 1case class User(name: String) 2case class Insight(desc: String) 4def lowLevelMakeUser 5(db: DbConfig, name: String): IO[User] = 6User(name).pure[IO] 8def lowLevelGetInsight 9(db: DbConfig, metrics: MetricsConfig, user: User) 10: IO[Insight] = 11IO { 12val username = System getenv "USER" 13Insight(s"likes username: ${username}") 14} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 37 / 46
  • 38. Write agnostic computations Mid-level composition 1def makeUser[M[_]] 2(name: String)(implicit D: MonadDb[M]): M[User] = 3for { 4conf <- D.dbConfig 5user <- lowLevelMakeUser(conf, name).liftBase[M] 6} yield user 8def getInsight[M[_]] 9(user: User)(implicit D: MonadDb[M], M: MonadMetrics[M]) 10: M[Insight] = 11for { 12db <- D.dbConfig 13metrics <- M.metricsConfig 14insight <- 15lowLevelGetInsight(db, metrics, user).liftBase[M] 16} yield insight Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 38 / 46
  • 39. Write agnostic computations One more mid-level 1def showInsight[M[_] : MonadBase[IO, ?[_]]] 2(user: User, insight: Insight): M[Unit] = 3IO{ println(s"${user.name} ${insight.desc}") }.liftBase[M] Our final application 1def app[M[_] : MonadDb : MonadMetrics]: M[Unit] = 2for { 3user <- makeUser[M]("Sukant") 4insight <- getInsight[M](user) 5_ <- showInsight[M](user, insight) 6} yield () Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 39 / 46
  • 40. The end of the world 1val conf = AppConfig(DbConfig(), MetricsConfig()) 1scala> app[App].run.run(conf).unsafeRun 2Sukant likes username: shajra Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 40 / 46
  • 41. Effect Commutativity Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 41 / 46
  • 42. We don’t have to specify a stack order 1type StateEff[F[_]] = MonadState[Int, F] 2type ErrorEff[F[_]] = MonadError[String, F] 4def tryMtl[F[_] : ErrorEff : StateEff] = { 5val attempt = 6for { 7_ <- 1.put[F] 8_ <- "oh noes".raiseError[F, Unit] 9} yield () 10attempt.handleError(_ => ().pure[F]) 11} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 42 / 46
  • 43. Different stacks, different results Stack Representation StateT[Int, EitherT[String, Identity, ?], A] S =>M[Either[E, (S, A)]] EitherT[String, StateT[Int, Identity, ?], A] S =>M[(S, Either[E, A])] 1type StackSE[A] = 2StateT[Int, EitherT[String, Identity, ?], A] 3type StackES[A] = 4EitherT[String, StateT[Int, Identity, ?], A] 1scala> tryMtl[StackSE].run(0).run.run 2res1: scalaz./[String,(Int, Unit)] = /-((0,())) 4scala> tryMtl[StackES].run.run(0).run 5res2: (Int, scalaz./[String,Unit]) = (1,/-(())) Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 43 / 46
  • 44. Trying with Eff 1import cats.data._; import cats.syntax.all._ 2import org.atnos.eff._; import org.atnos.eff.all._ 3import org.atnos.eff.syntax.all._ 5type StateEff[A] = State[Int, A] 6type ErrorEff[A] = Either[String, A] 8def tryEff[R] 9(implicit S: StateEff |= R , W: ErrorEff /= R) 10: Eff[R, Unit] = { 11val attempt: Eff[R, Unit] = 12for { 13_ <- put(1) 14_ <- left[R, String, Unit]("oh noes") 15} yield () 16catchLeft[R, String, Unit](attempt) { _ => 17().pure[Eff[R, ?]] 18} 19} Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 44 / 46
  • 45. By default, interpretation locked in 1scala> type StackSE = Fx.fx2[StateEff, ErrorEff] 2defined type alias StackSE 4scala> type StackES = Fx.fx2[ErrorEff, StateEff] 5defined type alias StackES 7scala> tryEff[StackSE].runState(0).runEither.run 8res2: scala.util.Either[String,(Unit, Int)] = Right(((),1)) 10scala> tryEff[StackSE].runEither.runState(0).run 11res3: (scala.util.Either[String,Unit], Int) = (Right(()),1) 13scala> tryEff[StackES].runState(0).runEither.run 14res4: scala.util.Either[String,(Unit, Int)] = Right(((),1)) 16scala> tryEff[StackES].runEither.runState(0).run 17res5: (scala.util.Either[String,Unit], Int) = (Right(()),1) Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 45 / 46
  • 46. Wrapping up Sukant Hajra / @shajra Classy Monad Transformers (Stop Eff’ing) March 24, 2017 46 / 46