SlideShare a Scribd company logo
Classy Monad Transformers (Stop Eļ¬€ā€™ing)
Sukant Hajra / @shajra
March 24, 2017
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 2 / 46
Quick mention
Figure 1: My Employer
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 7 / 46
Towards Transformers
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 9 / 46
A ļ¬rst 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 reļ¬‚ection)
feels like ā€œmanualā€ dependency injection
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 13 / 46
A second response
Beneļ¬ts
Plumbing is hidden a little.
Weā€™re getting some composition.
Complaints
A global conļ¬g is anti-modular.
Side-eļ¬€ects! Is this even FP?
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™ing) March 24, 2017 14 / 46
Eļ¬€ect-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 Eļ¬€ā€™ing) March 24, 2017 15 / 46
Eļ¬€ect-tracking types
No side-eļ¬€ects 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 Eļ¬€ā€™ing) March 24, 2017 16 / 46
Thus far we have
Two monads
Reader passes in a parameters
IO tracks an eļ¬€ect
Is composing them useful?
Reader[IO[A]]
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 ļ¬‚atten F[F[A]] and G[G[A]]
Itā€™s hard to ļ¬‚atten F[G[F[G[A]]]].
Can we compose IO and Reader speciļ¬cally?
Yes, thatā€™s exactly what monad transformers do.
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 23 / 46
Using stacks with parametric polymorphism
Stack not speciļ¬ed, 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 speciļ¬ed when run
1scala> abstractlyBuilt[Stack].run(1).unsafeRun
2res18: (String, Int) = (hi,1)
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™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 ļ¬x, you donā€™t have to
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 27 / 46
Some transformers commute eļ¬€ects
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 eļ¬€ects
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 Eļ¬€ā€™ing) March 24, 2017 28 / 46
What have we got thus far?
Improvements
separations of concerns (Reader from IO)
no side-eļ¬€ects
Remaining Complaint
still using a global conļ¬guration
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™ing) March 24, 2017 29 / 46
Classy Monad Transformers Example
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™ing) March 24, 2017 30 / 46
Setup
Using a fork of AloĆÆs Cochardā€™s ā€œscato-styleā€ Scalaz 8
1import scalaz.Prelude.Base._
Notable diļ¬€erences
minimal subtyping
SI-2712 ļ¬xed!
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™ing) March 24, 2017 31 / 46
Some abstractions
Our conļ¬guration from before
1case class DbConfig()
2case class MetricsConfig()
3case class AppConfig(db: DbConfig, metrics: MetricsConfig)
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 ļ¬nal 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 Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 40 / 46
Eļ¬€ect Commutativity
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 42 / 46
Diļ¬€erent stacks, diļ¬€erent 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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 45 / 46
Wrapping up
Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™ing) March 24, 2017 46 / 46

More Related Content

What's hot

Category Theory for Programmers
Category Theory for ProgrammersCategory Theory for Programmers
Category Theory for Programmers
Santosh 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 2
Philip 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 generators
Philip 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 engineers
Pranav 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 Cats
Philip Schwarz
Ā 
Sequence and Traverse - Part 3
Sequence and Traverse - Part 3Sequence and Traverse - Part 3
Sequence and Traverse - Part 3
Philip Schwarz
Ā 
19. Data Structures and Algorithm Complexity
19. Data Structures and Algorithm Complexity19. Data Structures and Algorithm Complexity
19. Data Structures and Algorithm Complexity
Intro C# Book
Ā 
Functor Composition
Functor CompositionFunctor Composition
Functor Composition
Philip Schwarz
Ā 
JAVA OOP
JAVA OOPJAVA OOP
JAVA OOP
Sunil OS
Ā 
Templates
TemplatesTemplates
Templates
Nilesh Dalvi
Ā 
Functors
FunctorsFunctors
Functors
Philip Schwarz
Ā 
Whiteboarding Coding Challenges in Python
Whiteboarding Coding Challenges in PythonWhiteboarding Coding Challenges in Python
Whiteboarding Coding Challenges in Python
Andrew Ferlitsch
Ā 
Python for data analysis
Python for data analysisPython for data analysis
Python for data analysis
Savitribai Phule Pune University
Ā 
Scala jargon cheatsheet
Scala jargon cheatsheetScala jargon cheatsheet
Scala jargon cheatsheet
Ruslan Shevchenko
Ā 
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
CP-Union
Ā 
Monads do not Compose
Monads do not ComposeMonads do not Compose
Monads do not Compose
Philip Schwarz
Ā 
Approximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming ApplicationsApproximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming Applications
Debasish Ghosh
Ā 
Java introduction
Java introductionJava introduction
Java introduction
Samsung Electronics Egypt
Ā 
Array ppt
Array pptArray ppt
Array ppt
Kaushal Mehta
Ā 

What's hot (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
Ā 

Viewers also liked

Understanding Your Metadataā€™s Journey
Understanding Your Metadataā€™s JourneyUnderstanding Your Metadataā€™s Journey
Understanding Your Metadataā€™s Journey
BookNet 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 Learning
Wes McKinney
Ā 
Scala Validation with Functional Programming
Scala Validation with Functional ProgrammingScala Validation with Functional Programming
Scala Validation with Functional Programming
Sukant Hajra
Ā 
42.type: Literal-based Singleton types
42.type: Literal-based Singleton types42.type: Literal-based Singleton types
42.type: Literal-based Singleton types
George 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 Microservices
Bora Tunca
Ā 
Paper battery in IEEE format
Paper battery in IEEE formatPaper battery in IEEE format
Paper battery in IEEE format
Sivabala Nedunchezhiyan
Ā 
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
Wes 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 Example
Connie Chen
Ā 
Ieee paper format
Ieee paper formatIeee paper format
Ieee paper format
Sameer Hudli
Ā 
Ieee slide format
Ieee slide formatIeee slide format
Ieee slide format
Sameer Hudli
Ā 
Make your programs Free
Make your programs FreeMake your programs Free
Make your programs Free
Pawel Szulc
Ā 
IEEE Presentation
IEEE PresentationIEEE Presentation
IEEE PresentationMohamed Tawfik
Ā 
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
BookNet 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 sufferers
Celine 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 Runner
Armelle Gilliard
Ā 
The Crazy Cuban's Secret
The  Crazy Cuban's   SecretThe  Crazy Cuban's   Secret
The Crazy Cuban's Secret
Lazaro Almenares
Ā 
Dementia: An Overview
Dementia: An OverviewDementia: An Overview
Dementia: An Overview
Irene Ryan
Ā 
Secret encoder ring
Secret encoder ringSecret encoder ring
Secret encoder ring
Toby 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ĆØte
Maxime Blanc-Fontes
Ā 

Viewers also liked (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
Ā 

Similar to Classy Monad Transformers (Stop Eff'ing Around)

Advance Scala - Oleg MĆ¼rk
Advance Scala - Oleg MĆ¼rkAdvance Scala - Oleg MĆ¼rk
Advance Scala - Oleg MĆ¼rk
Planet 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 2021
Peng Cheng
Ā 
Kyo - Functional Scala 2023.pdf
Kyo - Functional Scala 2023.pdfKyo - Functional Scala 2023.pdf
Kyo - Functional Scala 2023.pdf
Flavio 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 Mayavi
Enthought, Inc.
Ā 
Functional Reactive Programming on Android
Functional Reactive Programming on AndroidFunctional Reactive Programming on Android
Functional Reactive Programming on Android
Sam 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...
Piotr Paradziński
Ā 
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
Ā 
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdfbreaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
VishalKumarJha10
Ā 
Practical cats
Practical catsPractical cats
Practical cats
Raymond Tay
Ā 
Oops recap
Oops recapOops recap
Oops recapNiit Care
Ā 
Methods
MethodsMethods
Seeing Like Software
Seeing Like SoftwareSeeing Like Software
Seeing Like Software
Andrew Lovett-Barron
Ā 
Functional programming-advantages
Functional programming-advantagesFunctional programming-advantages
Functional programming-advantages
Sergei Winitzki
Ā 
Real world cats
Real world catsReal world cats
Real world cats
Ikhoon 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).pdf
Central 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 matlab
SalanSD
Ā 
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-Learn
Gilles Louppe
Ā 

Similar to Classy Monad Transformers (Stop Eff'ing Around) (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...
Ā 
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdfbreaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
Ā 
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
Ā 

Recently uploaded

Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
Ā 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
Roshan Dwivedi
Ā 
AI Genie Review: Worldā€™s First Open AI WordPress Website Creator
AI Genie Review: Worldā€™s First Open AI WordPress Website CreatorAI Genie Review: Worldā€™s First Open AI WordPress Website Creator
AI Genie Review: Worldā€™s First Open AI WordPress Website Creator
Google
Ā 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Octavian Nadolu
Ā 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
Ā 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
Ā 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata
Ā 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
Ā 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
Ā 
Need for Speed: Removing speed bumps from your Symfony projects āš”ļø
Need for Speed: Removing speed bumps from your Symfony projects āš”ļøNeed for Speed: Removing speed bumps from your Symfony projects āš”ļø
Need for Speed: Removing speed bumps from your Symfony projects āš”ļø
Łukasz Chruściel
Ā 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
Alina Yurenko
Ā 
AI Pilot Review: The Worldā€™s First Virtual Assistant Marketing Suite
AI Pilot Review: The Worldā€™s First Virtual Assistant Marketing SuiteAI Pilot Review: The Worldā€™s First Virtual Assistant Marketing Suite
AI Pilot Review: The Worldā€™s First Virtual Assistant Marketing Suite
Google
Ā 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni GarcĆ­a
Ā 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
Ā 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
Ā 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
Ā 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
Ā 
Atelier - Innover avec lā€™IA GĆ©nĆ©rative et les graphes de connaissances
Atelier - Innover avec lā€™IA GĆ©nĆ©rative et les graphes de connaissancesAtelier - Innover avec lā€™IA GĆ©nĆ©rative et les graphes de connaissances
Atelier - Innover avec lā€™IA GĆ©nĆ©rative et les graphes de connaissances
Neo4j
Ā 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
Ā 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
Ā 

Recently uploaded (20)

Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Ā 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
Ā 
AI Genie Review: Worldā€™s First Open AI WordPress Website Creator
AI Genie Review: Worldā€™s First Open AI WordPress Website CreatorAI Genie Review: Worldā€™s First Open AI WordPress Website Creator
AI Genie Review: Worldā€™s First Open AI WordPress Website Creator
Ā 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Ā 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Ā 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Ā 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
Ā 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Ā 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Ā 
Need for Speed: Removing speed bumps from your Symfony projects āš”ļø
Need for Speed: Removing speed bumps from your Symfony projects āš”ļøNeed for Speed: Removing speed bumps from your Symfony projects āš”ļø
Need for Speed: Removing speed bumps from your Symfony projects āš”ļø
Ā 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
Ā 
AI Pilot Review: The Worldā€™s First Virtual Assistant Marketing Suite
AI Pilot Review: The Worldā€™s First Virtual Assistant Marketing SuiteAI Pilot Review: The Worldā€™s First Virtual Assistant Marketing Suite
AI Pilot Review: The Worldā€™s First Virtual Assistant Marketing Suite
Ā 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Ā 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Ā 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Ā 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
Ā 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Ā 
Atelier - Innover avec lā€™IA GĆ©nĆ©rative et les graphes de connaissances
Atelier - Innover avec lā€™IA GĆ©nĆ©rative et les graphes de connaissancesAtelier - Innover avec lā€™IA GĆ©nĆ©rative et les graphes de connaissances
Atelier - Innover avec lā€™IA GĆ©nĆ©rative et les graphes de connaissances
Ā 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ā 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Ā 

Classy Monad Transformers (Stop Eff'ing Around)

  • 1. Classy Monad Transformers (Stop Eļ¬€ā€™ing) Sukant Hajra / @shajra March 24, 2017 Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 2 / 46
  • 3. Quick mention Figure 1: My Employer Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 7 / 46
  • 8. Towards Transformers Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 9 / 46
  • 10. A ļ¬rst 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 reļ¬‚ection) feels like ā€œmanualā€ dependency injection Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 13 / 46
  • 14. A second response Beneļ¬ts Plumbing is hidden a little. Weā€™re getting some composition. Complaints A global conļ¬g is anti-modular. Side-eļ¬€ects! Is this even FP? Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™ing) March 24, 2017 14 / 46
  • 15. Eļ¬€ect-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 Eļ¬€ā€™ing) March 24, 2017 15 / 46
  • 16. Eļ¬€ect-tracking types No side-eļ¬€ects 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 Eļ¬€ā€™ing) March 24, 2017 16 / 46
  • 17. Thus far we have Two monads Reader passes in a parameters IO tracks an eļ¬€ect Is composing them useful? Reader[IO[A]] Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 ļ¬‚atten F[F[A]] and G[G[A]] Itā€™s hard to ļ¬‚atten F[G[F[G[A]]]]. Can we compose IO and Reader speciļ¬cally? Yes, thatā€™s exactly what monad transformers do. Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 23 / 46
  • 24. Using stacks with parametric polymorphism Stack not speciļ¬ed, 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 speciļ¬ed when run 1scala> abstractlyBuilt[Stack].run(1).unsafeRun 2res18: (String, Int) = (hi,1) Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™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 ļ¬x, you donā€™t have to Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 27 / 46
  • 28. Some transformers commute eļ¬€ects 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 eļ¬€ects 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 Eļ¬€ā€™ing) March 24, 2017 28 / 46
  • 29. What have we got thus far? Improvements separations of concerns (Reader from IO) no side-eļ¬€ects Remaining Complaint still using a global conļ¬guration Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™ing) March 24, 2017 29 / 46
  • 30. Classy Monad Transformers Example Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 diļ¬€erences minimal subtyping SI-2712 ļ¬xed! Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™ing) March 24, 2017 31 / 46
  • 32. Some abstractions Our conļ¬guration from before 1case class DbConfig() 2case class MetricsConfig() 3case class AppConfig(db: DbConfig, metrics: MetricsConfig) Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™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 ļ¬nal 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 Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 40 / 46
  • 41. Eļ¬€ect Commutativity Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 42 / 46
  • 43. Diļ¬€erent stacks, diļ¬€erent 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 Eļ¬€ā€™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 Eļ¬€ā€™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 Eļ¬€ā€™ing) March 24, 2017 45 / 46
  • 46. Wrapping up Sukant Hajra / @shajra Classy Monad Transformers (Stop Eļ¬€ā€™ing) March 24, 2017 46 / 46