SlideShare ist ein Scribd-Unternehmen logo
1 von 118
Downloaden Sie, um offline zu lesen
The Death of Tagless Final
John A. De Goes — @jdegoes
Wiem Zine Elabidine — @wiemzin
Amsterdam.scala & FP AMS
Xebia, Amsterdam
March 2, 2019
SPECIAL THANKS
Amsterdam.scala
FP AMS
First-Class Effects Tagless Final
ZIO Environment Wrap Up
FIRST-CLASS EFFECTS
PROGRAMS AS STATEMENTS
def main: Unit = {
println("Good morning, what is your name?")
val name = readLine()
println(s"Good to meet you, $name!")
}
PROGRAMS AS STATEMENTS
val example: Double = …
val value = example
val values = List.fill(10)(value)
val plusone = value => value + 1
PROGRAMS AS STATEMENTS
def main: Unit = …
val program = main
val programs = List.fill(10)(main)
val retried = program =>
program.retried(2.times)
BENEFITS OF VALUES
Abstraction
Friendly
Refactor
Friendly
Test
Friendly
BENEFITS OF VALUES
def main: Unit = {
println("Good morning, what is your name?")
val name = readLine()
println(s"Good to meet you, $name!")
}
Procedural
Effects
Functional
Effects
Functional effects are immutable data structures
that merely describe sequences of operations.
At the end of the world, the data structure has to
be impurely “interpreted” to real world effects.
println("Hello World")
Procedural Effects “Do”
case class PrintLine(text: String)
Functional Effects “Describe”
PROGRAMS AS VALUES
IO[A]
A description of an effect that when unsafely
interpreted, will succeed with a value of type A
PROGRAMS AS VALUES
class IO[+A](val unsafeInterpret: () => A) { s =>
def map[B](f: A => B) = flatMap(f.andThen(IO.effect(_)))
def flatMap[B](f: A => IO[B]): IO[B] =
IO.effect(f(s.unsafeInterpret()).unsafeInterpret())
}
object IO {
def effect[A](eff: => A) = new IO(() => eff)
}
PROGRAMS AS VALUES
def putStrLn(line: String): IO[Unit] =
IO.effect(println(line))
val getStrLn: IO[String] =
IO.effect(scala.io.StdIn.readLine())
PROGRAMS AS VALUES
val main = for {
_ <- putStrLn("Good morning, " +
"what is your name?")
name <- getStrLn
_ <- putStrLn(s"Good to meet you, $name!")
} yield ()
PROGRAMS AS VALUES
val main = …
val program = main
val programs = List.fill(10)(main)
val retried = program =>
program.retried(2.times)
PROGRAMS AS VALUES
def loadTest(url: String, n: Int) =
val policy = Schedule.recurs(10).jittered
val worker = client.get(url).retry(policy)
val workers = List.fill(n)(worker)
IO.collectAllPar(workers)
}
PROGRAMS AS VALUES
def loadTest(url: String, n: Int) =
val policy = Schedule.recurs(10).jittered
val worker = client.get(url).retry(policy)
val workers = List.fill(n)(worker)
IO.collectAllPar(workers)
}
PROGRAMS AS VALUES
def loadTest(url: String, n: Int) =
val policy = Schedule.recurs(10).jittered
val worker = client.get(url).retry(policy)
val workers = List.fill(n)(worker)
IO.collectAllPar(workers)
}
PROGRAMS AS VALUES
def loadTest(url: String, n: Int) =
val policy = Schedule.recurs(10).jittered
val worker = client.get(url).retry(policy)
val workers = List.fill(n)(worker)
IO.collectAllPar(workers)
}
Functional Effects
Abstraction
Friendly
Refactor
Friendly
Test
Friendly
But!
Functional Effects
Abstraction
Friendly
Refactor
Friendly
Test
Friendly
PROGRAMS AS (OPAQUE) VALUES
def putStrLn(line: String): IO[Unit] =
IO.effect(println(line))
val getStrLn: IO[String] =
IO.effect(scala.io.StdIn.readLine())
TAGLESS-FINAL
BACK TO BASICS: JAVA 101
interface Console {
void println(String line);
String readLine();
}
BACK TO BASICS: JAVA 101
public void program(Console console) {
console.println("Good morning, " +
"what is your name?");
String name = console.readLine();
console.println(s"Good to meet you, $name!");
}
BACK TO BASICS: JAVA 101
class LiveConsole implements Console { … }
class TestConsole implements Console { … }
// In production:
program(new LiveConsole());
// In tests:
program(new TestConsole());
Purely!
IO INTERFACES
trait Console {
def println(line: String): IO[Unit]
val readLine: IO[String]
}
PURE PROGRAM WITH INTERFACE
def program(c: Console) = for {
_ <- c.println("Good morning, " +
"what is your name?")
name <- c.readLine
_ <- c.println(s"Good to meet you, $name!")
} yield ()
POLYMORPHIC EFFECT
trait Console[IO[_]] {
def println(String line): IO[Unit]
val readLine: IO[String]
}
MAKING IT EVEN MORE OBSCURE
trait Console[F[_]] {
def println(String line): F[Unit]
val readLine: F[String]
}
THE GLORIOUS TAGLESS-FINAL TYPE CLASS
trait Console[F[_]] {
def println(String line): F[Unit]
val readLine: F[String]
}
object Console {
def apply[F[_]](implicit F: Console[F]) = F
}
EFFECT-POLYMORPHIC PROGRAMS
def program[F[_]: Console: Monad] = for {
_ <- Console[F].println(
"Good morning, " +
"what is your name?")
name <- Console[F].readLine
_ <- Console[F].println(
s"Good to meet you, $name!")
} yield ()
TEST VS PRODUCTION EFFECTS
case class TestIO[A](...)
implicit val TestConsole = new Console[TestIO] { … }
implicit val LiveConsole = new Console[IO] { … }
// In production:
program[IO] : IO[Unit]
// In tests:
program[TestIO] : TestIO[Unit]
Functional Effects
Abstraction
Friendly
Refactor
Friendly
Test
Friendly
Functional Effects
Abstraction
Friendly
Refactor
Friendly
Test
Friendly
TAGLESS-FINAL IS EASY!
Functional Effects
IO[A]
TAGLESS-FINAL IS PRETTY EASY!
Functional Effects Parametric Polymorphism
F
TAGLESS-FINAL IS EASY-ISH!
Functional Effects Parametric Polymorphism
F[_]
Higher-Kinded Types
TAGLESS-FINAL ISN’T THAT HARD!
Functional Effects Parametric Polymorphism
trait Console[F[_]] { … }
Higher-Kinded Types Type Classes
TAGLESS-FINAL COULD BE MUCH HARDER!
Functional Effects Parametric Polymorphism
implicit val TestConsole = new Console[TestIO] { … }
Higher-Kinded Types Type Classes
Type Class Instances
TAGLESS-FINAL IS SORT OF HARD!
Functional Effects Parametric Polymorphism
new Console[({type F[A] = State[TestData, A]})#F] { … }
Higher-Kinded Types Type Classes
Type Class Instances Partial Type Application
OMG, TAGLESS-FINAL IS THE WORST!!!
Functional Effects Parametric Polymorphism
def program[F[_]: Monad: Console: Database] = ...
Higher-Kinded Types Type Classes
Type Class Instances Partial Type Application Monad Hierarchy
TAGLESS-FINAL IS MANY THINGS
EASY IS NOT ONE OF THEM
☠ TYPE CLASS ABUSE ☠
THE DARK SIDE OF TAGLESS-FINAL
REAL TYPE CLASS
Defines common
structure across types
through lawful
operations, enabling
abstraction.
FAKE TYPE CLASS
Defines a common
interface across types
through ad hoc
polymorphism,
enabling testing.
☠ TYPE CLASS ABUSE ☠
THE DARK SIDE OF TAGLESS-FINAL
REAL TYPE CLASS
Defines common
structure across types
through lawful
operations, enabling
abstraction.
FAKE TYPE CLASS
Defines a common
interface across types
through ad hoc
polymorphism,
enabling testing.
☠ BIG BANG INTRODUCTION ☠
THE DARK SIDE OF TAGLESS-FINAL
def program[F[_]: Console: Monad] = for {
_ <- Console[F].println(
"Good morning, " +
"what is your name?")
name <- Console[F].readLine
_ <- Console[F].println(
s"Good to meet you, $name!")
} yield ()
☠ TEDIOUS REPETITION ☠
THE DARK SIDE OF TAGLESS-FINAL
def genFeed[F[_]: Monad:
Logging: UserDatabase:
ProfileDatabase: RedisCache:
GeoIPService: AuthService:
SessionManager: Localization:
Config: EventQueue: Concurrent:
Async: MetricsManager]: F[Feed] = ???
☠ STUBBORN REPETITION ☠
THE DARK SIDE OF TAGLESS-FINAL
def genFeed[F[_]: Everything]: F[Feed] =
???
☠ COMPLETELY NON-INFERABLE ☠
THE DARK SIDE OF TAGLESS-FINAL
def genFeed = ???
☠ FAKE PARAMETRIC GUARANTEES ☠
def innocent[F[_]: Monad]: F[Unit] = {
def effect[A](a: => A): F[A] =
Monad[F].point(()).map(_ => a)
println("What guarantees?")
effect(System.exit(42))
}
THE DARK SIDE OF TAGLESS-FINAL
THE DEATH OF TAGLESS-FINAL
THE DEATH OF TAGLESS-FINAL
ZIO ENVIRONMENT
ZIO is a zero-dependency Scala library for
asynchronous and concurrent programming.
High-Performance
Γ
Type-Safe
ǁ
Concurrent
⇅
Asynchronous Resource-Safe
✓
Testable
Resilient
λ
Functional
BACK TO BASICS
trait Console {
def println(line: String): IO[Unit]
val readLine: IO[String]
}
BACK TO BASICS
def program(c: Console) = for {
_ <- c.println("Good morning, " +
"What is your name?")
name <- c.readLine
_ <- c.println(s"Good to meet you, $name!")
} yield ()
BACK TO BASICS
def program(c: Console, p: Persistence) = for {
_ <- c.println("Good morning, " +
"what is your name?")
name <- c.readLine
_ <- p.savePreferences(name)
_ <- c.println(s"Good to meet you, $name!")
} yield ()
BACK TO BASICS
def program(s1: Service1, s2: Service2,
s3: Service3, … sn: ServiceN) =
for {
a <- foo(s1, s9, s3)("localhost", 42)
b <- bar(sn, s19, s3)(a, 1024)
...
} yield z
BACK TO BASICS
def program(s1: Service1, s2: Service2,
s3: Service3, … sn: ServiceN) =
for {
a <- foo(s1, s9, s3)("localhost", 42)
b <- bar(sn, s19, s3)(a, 1024)
...
} yield z
THE MODULE PATTERN
trait HasConsole {
def console: HasConsole.Service
}
object HasConsole {
trait Service {
def println(line: String): IO[Unit]
val readLine: IO[String]
}
}
THE MODULE PATTERN
trait HasConsole {
def console: HasConsole.Service
}
object HasConsole {
trait Service {
def println(line: String): IO[Unit]
val readLine: IO[String]
}
}
THE MODULE PATTERN
def program(s: HasConsole with HasPersistence) =
for {
_ <- s.console.println("What is your name?")
name <- s.console.readLine
_ <- s.persistence.savePreferences(name)
_ <- s.console.println(s"Good to meet” +
” you, $name!")
} yield ()
THE MODULE PATTERN
def program(s: HasService1 with … HasServiceN) =
for {
a <- foo(s)("localhost", 42)
b <- bar(s)(a, 1024)
...
} yield z
THE READER MONAD
case class Reader[-R, +A](provide: R => A) { self =>
def map[B](f: A => B) = flatMap(a => Reader.point(f(a)))
def flatMap[R1 <: R, B](f: A => Reader[R1, B]) =
Reader[R, B](r => f(self.provide(r)).provide(r))
}
object Reader {
def point[A](a: => A): Reader[Any, A] = Reader(_ => a)
def environment[R]: Reader[R, R] = Reader(identity)
}
THE READER MONAD
def program: Reader[HasService1 with ..., Unit] =
for {
a <- foo("localhost", 42)
b <- bar(a, 1024)
...
} yield z
THE READER MONAD TRANSFORMER
ReaderT[IO, R, A]
THE READER MONAD TRANSFORMER
ReaderT[IO, R, A]
IO
ReaderT
ZIO ENVIRONMENT
ZIO ENVIRONMENT
ZIO ENVIRONMENT
ZIO[R, E, A]*
ZIO ENVIRONMENT
ZIO[R, E, A]*
type UIO [ +A] = ZIO[Any, Nothing, A]
type Task[ +A] = ZIO[Any, Throwable, A]
type IO [+E, +A] = ZIO[Any, E, A]
*
ZIO ENVIRONMENT
ZIO[R, E, A]
Environment Type
ZIO ENVIRONMENT
ZIO[R, E, A]
Failure Type
ZIO ENVIRONMENT
ZIO[R, E, A]
Success Type
ZIO ENVIRONMENT
ZIO[Console, IOException, Unit]
Requires Console
ZIO ENVIRONMENT
Might Fail with
IOException
ZIO[Console, IOException, Unit]
ZIO ENVIRONMENT
Might Succeed
with Unit
ZIO[Console, IOException, Unit]
ZIO ENVIRONMENT: EXAMPLE
val program: ZIO[Console with Persistence, IOException, Unit] =
for {
_ <- putStrLn("Good morning, what is your name?")
name <- getStrLn
_ <- savePreferences(name)
_ <- putStrLn(s"Good to meet you, $name!")
} yield ()
ZIO ENVIRONMENT: CORE
sealed trait ZIO[-R, +E, +A] {
...
def provide(environment: R): ZIO[Any, E, A] = ...
}
object ZIO {
def accessM[R, E, A](f: R => ZIO[R, E, A]): ZIO[R, E, A] = ...
def access[R, E, A](f: R => A): ZIO[R, Nothing, A] =
accessM(ZIO.succeed(_))
def environment[R]: ZIO[R, Nothing, R] = access(identity)
}
ZIO ENVIRONMENT: CORE
sealed trait ZIO[-R, +E, +A] {
...
def provide(environment: R): ZIO[Any, E, A] = ...
}
object ZIO {
def accessM[R, E, A](f: R => ZIO[R, E, A]): ZIO[R, E, A] = ...
def access[R, E, A](f: R => A): ZIO[R, Nothing, A] =
accessM(ZIO.succeed(_))
def environment[R]: ZIO[R, Nothing, R] = access(identity)
}
ZIO ENVIRONMENT: CORE
sealed trait ZIO[-R, +E, +A] {
...
def provide(environment: R): ZIO[Any, E, A] = ...
}
object ZIO {
def accessM[R, E, A](f: R => ZIO[R, E, A]): ZIO[R, E, A] = ...
def access[R, E, A](f: R => A): ZIO[R, Nothing, A] =
accessM(ZIO.succeed(_))
def environment[R]: ZIO[R, Nothing, R] = access(identity)
}
ZIO ENVIRONMENT: CORE
sealed trait ZIO[-R, +E, +A] {
...
def provide(environment: R): ZIO[Any, E, A] = ...
}
object ZIO {
def accessM[R, E, A](f: R => ZIO[R, E, A]): ZIO[R, E, A] = ...
def access[R, E, A](f: R => A): ZIO[R, Nothing, A] =
accessM(ZIO.succeed(_))
def environment[R]: ZIO[R, Nothing, R] = access(identity)
}
ZIO ENVIRONMENT: TUTORIAL
// Module (contains service)
trait Console {
def console: Console.Service
}
ZIO ENVIRONMENT: TUTORIAL
object Console {
// Service definition:
trait Service {
def println(line: String): ZIO[Any, Nothing, Unit]
val readLine: ZIO[Any, IOException, String]
}
}
ZIO ENVIRONMENT: TUTORIAL
object ConsoleLive extends Console {
val console = new Console.Service {
def println(line: String): UIO[Unit] =
ZIO.effectTotal(scala.io.StdIn.println(line))
val readLine: IO[IOException, String] =
ZIO.effect(scala.io.StdIn.readLine()).refineOrDie {
case e : IOException => e
}
}
}
ZIO ENVIRONMENT: TUTORIAL
// Optional (but handy!) helpers:
package object console {
def println(line: String): ZIO[Console, Nothing, Unit] =
ZIO.accessM(_.console println line)
val readLine: ZIO[Console, IOException, String] =
ZIO.accessM(_.console.readLine)
}
ZIO ENVIRONMENT: TUTORIAL
val program: ZIO[Console, IOException, Unit] =
for {
_ <- putStrLn("Good morning, what is your name?")
name <- getStrLn
_ <- putStrLn(s"Good to meet you, $name!")
} yield ()
DefaultRuntime.unsafeRun(program.provide(ConsoleLive))
ZIO ENVIRONMENT: TUTORIAL
object ConsoleTest extends Console {
...
}
DefaultRuntime.unsafeRun(program.provide(ConsoleTest))
ZIO ENVIRONMENT: TUTORIAL
val MyEnvironment: R = ...
val MyRuntime: Runtime[R] =
Runtime(MyEnvironment, PlatformLive)
Your Own R Platform (thread pool, etc.)
ZIO ENVIRONMENT: TEACHABLE
trait Console { def console: Console.Service }
object Console {
trait Service {
def println(line: String): ZIO[Any, Nothing, Unit]
val readLine: ZIO[Any, IOException, String]
}
}
object ConsoleLive extends Console.Service {
def println(line: String) = ZIO.effectTotal(scala.io.StdIn.println(line))
val readLine =
ZIO.effect(scala.io.StdIn.readLine()).refineOrDie(JustIOException)
}
Module
ZIO ENVIRONMENT: TEACHABLE
trait Console { def console: Console.Service }
object Console {
trait Service {
def println(line: String): ZIO[Any, Nothing, Unit]
val readLine: ZIO[Any, IOException, String]
}
}
object ConsoleLive extends Console.Service {
def println(line: String) = ZIO.effectTotal(scala.io.StdIn.println(line))
val readLine =
ZIO.effect(scala.io.StdIn.readLine()).refineOrDie(JustIOException)
}
Service
ZIO ENVIRONMENT: TEACHABLE
trait Console { def console: Console.Service }
object Console {
trait Service {
def println(line: String): ZIO[Any, Nothing, Unit]
val readLine: ZIO[Any, IOException, String]
}
}
object ConsoleLive extends Console.Service {
def println(line: String) = ZIO.effectTotal(scala.io.StdIn.println(line))
val readLine =
ZIO.effect(scala.io.StdIn.readLine()).refineOrDie(JustIOException)
}
Implementation
ZIO ENVIRONMENT: COMPOSABLE
trait Console { def console: Console.Service }
trait Logging { def logging: Logging.Service }
trait Persistence { def persistence: Persistence.Service }
...
val program: ZIO[Console with Logging with Persistence,
AppError, Unit] = ...
ZIO ENVIRONMENT: PERFORMANT
scala.concurrent.Future
ZIO ENVIRONMENT: FULLY INFERABLE
val program =
for {
_ <- putStrLn("Good morning, what is your name?")
name <- getStrLn
_ <- savePreferences(name)
_ <- log.debug("Saved $name to configuration")
_ <- putStrLn(s"Good to meet you, $name!")
} yield ()
ZIO ENVIRONMENT: FULLY INFERABLE
val program: ZIO[Console, Error, Unit] = ...
^^^^^^^
Found: Console
Expected: Console with Persistence with Logging with
Config with Auth
ZIO ENVIRONMENT: CONCISE
trait Console { def console: Console.Service }
trait Logging { def logging: Logging.Service }
trait Persistence { def persistence: Persistence.Service }
...
type ProgramEnv = Console with Logging with Persistence
val program: ZIO[ProgramEnv, AppError, Unit] = ...
ZIO ENVIRONMENT: CONCISE
trait Console { def console: Console.Service }
trait Logging { def logging: Logging.Service }
trait Persistence { def persistence: Persistence.Service }
...
type Program[A] = ZIO[Console with Logging with Persistence,
AppError, A]
val program: Program[Unit] = ...
ZIO ENVIRONMENT: MODULAR
def fn1: ZIO[R1, E, A] = {
def fn2: ZIO[R2, E, B] = ...
val localEnvironment: R2 = ...
val v1 = fn2.provide(localEnvironment)
...
}
val globalEnvironment: R1 = ...
val v2 = fn1.provide(globalEnvironment)
...
ZIO ENVIRONMENT: INCREMENTAL
// Deeply nested code:
val myCode: Task[Unit] = …
for {
...
result <- database.query(q)
...
} yield ()
ZIO ENVIRONMENT: INCREMENTAL
type TaskDB[A] = ZIO[Database, Throwable, A]
// Now fully testable!
def myCodeV2: TaskDB[Unit] = …
for {
...
result <- database.query(q)
...
} yield ()
THE REANIMATION OF TAGLESS-FINAL
THE REANIMATION OF TAGLESS-FINAL
trait HasState[S] {
def state: HasState.Service[S]
}
object HasState {
trait Service[S] {
def state: Ref[S]
}
}
THE REANIMATION OF TAGLESS-FINAL
implicit def MSZIO[S, R <: HasState[S], E]:
MonadState[ZIO[R, E, ?], S] =
new MonadState[ZIO[R, E, ?], S] {
...
}
...
def program[F[_]: MonadState[S, ?]]: F[Unit] = …
program[ZIO[HasState[S], E]]
THE REANIMATION OF TAGLESS-FINAL
implicit def MSZIO[S, R <: HasState[S], E]:
MonadState[ZIO[R, E, ?], S] =
new MonadState[ZIO[R, E, ?], S] {
...
}
...
def program[F[_]: MonadState[MySt, ?]]: F[Unit] = …
program[ZIO[HasState[MySt], Err]]
THE (RE)RISING OF CAKE
THE (RE)RISING OF CAKE
// Traditional MONOLITHIC cake
trait MyModule extends
CacheModule with LoggingModule with
DatabaseModule with AuthModule {
def refreshCache: Unit = ...
def genFeed : Feed = ...
def trace : Unit = ...
}
THE (RE)RISING OF CAKE
// Next-generation MODULAR cake
object MyFunctions {
val refreshCache: ZIO[Cache, Error, Unit] = ...
val genFeed: ZIO[Database with Auth, Error, Feed] = ...
val trace: ZIO[Debug, Nothing, Unit] = ...
}
WRAP UP
COMPARISON MATRIX
Transformers Free Monads Eff Tagless Final
Environmental
Effects
Composable ✔ ✔ ✔ ✔ ✔
Performance 𐄂 𐄂 𐄂 ✔ ✔
Reasoning Up to Discipline Up to Discipline Up to Discipline Up to Discipline Up to Discipline
Easily Teachable 𐄂 ? ✔ 𐄂 ✔
Concision 𐄂 𐄂 𐄂 𐄂 ✔
Full Type Inference 𐄂 𐄂 𐄂 𐄂 ✔
Modularity ✔ ✔ ✔ 𐄂 ✔
Pinpoint Testability 𐄂 𐄂 𐄂 𐄂 ✔
GETTING STARTED WITH ZIO
✨ github.com/scalaz/scalaz-zio
✨ gitter.im/scalaz/scalaz-zio
✨ scalaz.github.io/scalaz-zio
Thank You!
Any questions?
Stalk me online at @jdegoes
Follow Wiem online @wiemzin

Weitere ähnliche Inhalte

Was ist angesagt?

King’s candy crush saga
King’s candy crush sagaKing’s candy crush saga
King’s candy crush sagaCaleb Yoon
 
The practice of DeFi money lego
The practice of DeFi money legoThe practice of DeFi money lego
The practice of DeFi money legowei-li
 
[Paper] eXplainable ai(xai) in computer vision
[Paper] eXplainable ai(xai) in computer vision[Paper] eXplainable ai(xai) in computer vision
[Paper] eXplainable ai(xai) in computer visionSusang Kim
 
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingJohn De Goes
 
packages and interfaces
packages and interfacespackages and interfaces
packages and interfacesmadhavi patil
 
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]Ruslan Shevchenko
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Scott Wlaschin
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an examplePhilip Schwarz
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Mario Fusco
 
Tail Recursion in data structure
Tail Recursion in data structureTail Recursion in data structure
Tail Recursion in data structureRumman Ansari
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022Alexander Ioffe
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
 
Function template
Function templateFunction template
Function templateKousalya M
 
B.sc CSIT 2nd semester C++ Unit3
B.sc CSIT  2nd semester C++ Unit3B.sc CSIT  2nd semester C++ Unit3
B.sc CSIT 2nd semester C++ Unit3Tekendra Nath Yogi
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayDebasish Ghosh
 
Ad hoc Polymorphism using Type Classes and Cats
Ad hoc Polymorphism using Type Classes and CatsAd hoc Polymorphism using Type Classes and Cats
Ad hoc Polymorphism using Type Classes and CatsPhilip Schwarz
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Scott Wlaschin
 
Scikit-Learn: Machine Learning in Python
Scikit-Learn: Machine Learning in PythonScikit-Learn: Machine Learning in Python
Scikit-Learn: Machine Learning in PythonMicrosoft
 

Was ist angesagt? (20)

King’s candy crush saga
King’s candy crush sagaKing’s candy crush saga
King’s candy crush saga
 
The practice of DeFi money lego
The practice of DeFi money legoThe practice of DeFi money lego
The practice of DeFi money lego
 
[Paper] eXplainable ai(xai) in computer vision
[Paper] eXplainable ai(xai) in computer vision[Paper] eXplainable ai(xai) in computer vision
[Paper] eXplainable ai(xai) in computer vision
 
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
 
Zio in real world
Zio in real worldZio in real world
Zio in real world
 
packages and interfaces
packages and interfacespackages and interfaces
packages and interfaces
 
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
Tail Recursion in data structure
Tail Recursion in data structureTail Recursion in data structure
Tail Recursion in data structure
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
 
Function template
Function templateFunction template
Function template
 
B.sc CSIT 2nd semester C++ Unit3
B.sc CSIT  2nd semester C++ Unit3B.sc CSIT  2nd semester C++ Unit3
B.sc CSIT 2nd semester C++ Unit3
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
 
Ad hoc Polymorphism using Type Classes and Cats
Ad hoc Polymorphism using Type Classes and CatsAd hoc Polymorphism using Type Classes and Cats
Ad hoc Polymorphism using Type Classes and Cats
 
Python oop third class
Python oop   third classPython oop   third class
Python oop third class
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)
 
Scikit-Learn: Machine Learning in Python
Scikit-Learn: Machine Learning in PythonScikit-Learn: Machine Learning in Python
Scikit-Learn: Machine Learning in Python
 

Ähnlich wie The Death of Final Tagless

Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To ScalaInnar Made
 
Scala Quick Introduction
Scala Quick IntroductionScala Quick Introduction
Scala Quick IntroductionDamian Jureczko
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
Functional programming in Scala
Functional programming in ScalaFunctional programming in Scala
Functional programming in ScalaDamian Jureczko
 
Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009David Pollak
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to SwiftGiordano Scalzo
 
Generic Functional Programming with Type Classes
Generic Functional Programming with Type ClassesGeneric Functional Programming with Type Classes
Generic Functional Programming with Type ClassesTapio Rautonen
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my dayTor Ivry
 
Thinking Functionally with JavaScript
Thinking Functionally with JavaScriptThinking Functionally with JavaScript
Thinking Functionally with JavaScriptLuis Atencio
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Calvin Cheng
 
Learning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a NeckbeardLearning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a NeckbeardKelsey Gilmore-Innis
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In JavaAndrei Solntsev
 
Building a Functional Stream in Scala
Building a Functional Stream in ScalaBuilding a Functional Stream in Scala
Building a Functional Stream in ScalaDerek Wyatt
 
Functional programming in javascript
Functional programming in javascriptFunctional programming in javascript
Functional programming in javascriptBoris Burdiliak
 

Ähnlich wie The Death of Final Tagless (20)

Berlin meetup
Berlin meetupBerlin meetup
Berlin meetup
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To Scala
 
Scala Quick Introduction
Scala Quick IntroductionScala Quick Introduction
Scala Quick Introduction
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Functional programming in Scala
Functional programming in ScalaFunctional programming in Scala
Functional programming in Scala
 
Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009
 
Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
 
Generic Functional Programming with Type Classes
Generic Functional Programming with Type ClassesGeneric Functional Programming with Type Classes
Generic Functional Programming with Type Classes
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
 
Thinking Functionally with JavaScript
Thinking Functionally with JavaScriptThinking Functionally with JavaScript
Thinking Functionally with JavaScript
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)
 
Learning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a NeckbeardLearning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a Neckbeard
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
 
Building a Functional Stream in Scala
Building a Functional Stream in ScalaBuilding a Functional Stream in Scala
Building a Functional Stream in Scala
 
Functional programming in javascript
Functional programming in javascriptFunctional programming in javascript
Functional programming in javascript
 

Mehr von John De Goes

Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type ClassesJohn De Goes
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them AllJohn De Goes
 
Error Management: Future vs ZIO
Error Management: Future vs ZIOError Management: Future vs ZIO
Error Management: Future vs ZIOJohn De Goes
 
Atomically { Delete Your Actors }
Atomically { Delete Your Actors }Atomically { Delete Your Actors }
Atomically { Delete Your Actors }John De Goes
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: RebirthJohn De Goes
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: RebirthJohn De Goes
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018John De Goes
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New GameJohn De Goes
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsJohn De Goes
 
Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional ArchitectureJohn De Goes
 
The Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect SystemThe Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect SystemJohn De Goes
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsJohn De Goes
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free MonadsJohn De Goes
 
Streams for (Co)Free!
Streams for (Co)Free!Streams for (Co)Free!
Streams for (Co)Free!John De Goes
 
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...John De Goes
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and FutureJohn De Goes
 
All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!John De Goes
 
Getting Started with PureScript
Getting Started with PureScriptGetting Started with PureScript
Getting Started with PureScriptJohn De Goes
 

Mehr von John De Goes (20)

Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
 
Error Management: Future vs ZIO
Error Management: Future vs ZIOError Management: Future vs ZIO
Error Management: Future vs ZIO
 
Atomically { Delete Your Actors }
Atomically { Delete Your Actors }Atomically { Delete Your Actors }
Atomically { Delete Your Actors }
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: Rebirth
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: Rebirth
 
ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New Game
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka Actors
 
Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional Architecture
 
The Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect SystemThe Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect System
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free Monads
 
Streams for (Co)Free!
Streams for (Co)Free!Streams for (Co)Free!
Streams for (Co)Free!
 
MTL Versus Free
MTL Versus FreeMTL Versus Free
MTL Versus Free
 
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and Future
 
All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!
 
Getting Started with PureScript
Getting Started with PureScriptGetting Started with PureScript
Getting Started with PureScript
 

Kürzlich hochgeladen

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024SynarionITSolutions
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 

Kürzlich hochgeladen (20)

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 

The Death of Final Tagless

  • 1. The Death of Tagless Final John A. De Goes — @jdegoes Wiem Zine Elabidine — @wiemzin Amsterdam.scala & FP AMS Xebia, Amsterdam March 2, 2019
  • 2.
  • 4. First-Class Effects Tagless Final ZIO Environment Wrap Up
  • 6. PROGRAMS AS STATEMENTS def main: Unit = { println("Good morning, what is your name?") val name = readLine() println(s"Good to meet you, $name!") }
  • 7. PROGRAMS AS STATEMENTS val example: Double = … val value = example val values = List.fill(10)(value) val plusone = value => value + 1
  • 8. PROGRAMS AS STATEMENTS def main: Unit = … val program = main val programs = List.fill(10)(main) val retried = program => program.retried(2.times)
  • 10. BENEFITS OF VALUES def main: Unit = { println("Good morning, what is your name?") val name = readLine() println(s"Good to meet you, $name!") } Procedural Effects Functional Effects
  • 11. Functional effects are immutable data structures that merely describe sequences of operations. At the end of the world, the data structure has to be impurely “interpreted” to real world effects.
  • 13. case class PrintLine(text: String) Functional Effects “Describe”
  • 14. PROGRAMS AS VALUES IO[A] A description of an effect that when unsafely interpreted, will succeed with a value of type A
  • 15. PROGRAMS AS VALUES class IO[+A](val unsafeInterpret: () => A) { s => def map[B](f: A => B) = flatMap(f.andThen(IO.effect(_))) def flatMap[B](f: A => IO[B]): IO[B] = IO.effect(f(s.unsafeInterpret()).unsafeInterpret()) } object IO { def effect[A](eff: => A) = new IO(() => eff) }
  • 16. PROGRAMS AS VALUES def putStrLn(line: String): IO[Unit] = IO.effect(println(line)) val getStrLn: IO[String] = IO.effect(scala.io.StdIn.readLine())
  • 17. PROGRAMS AS VALUES val main = for { _ <- putStrLn("Good morning, " + "what is your name?") name <- getStrLn _ <- putStrLn(s"Good to meet you, $name!") } yield ()
  • 18. PROGRAMS AS VALUES val main = … val program = main val programs = List.fill(10)(main) val retried = program => program.retried(2.times)
  • 19. PROGRAMS AS VALUES def loadTest(url: String, n: Int) = val policy = Schedule.recurs(10).jittered val worker = client.get(url).retry(policy) val workers = List.fill(n)(worker) IO.collectAllPar(workers) }
  • 20. PROGRAMS AS VALUES def loadTest(url: String, n: Int) = val policy = Schedule.recurs(10).jittered val worker = client.get(url).retry(policy) val workers = List.fill(n)(worker) IO.collectAllPar(workers) }
  • 21. PROGRAMS AS VALUES def loadTest(url: String, n: Int) = val policy = Schedule.recurs(10).jittered val worker = client.get(url).retry(policy) val workers = List.fill(n)(worker) IO.collectAllPar(workers) }
  • 22. PROGRAMS AS VALUES def loadTest(url: String, n: Int) = val policy = Schedule.recurs(10).jittered val worker = client.get(url).retry(policy) val workers = List.fill(n)(worker) IO.collectAllPar(workers) }
  • 24. But!
  • 26. PROGRAMS AS (OPAQUE) VALUES def putStrLn(line: String): IO[Unit] = IO.effect(println(line)) val getStrLn: IO[String] = IO.effect(scala.io.StdIn.readLine())
  • 28. BACK TO BASICS: JAVA 101 interface Console { void println(String line); String readLine(); }
  • 29. BACK TO BASICS: JAVA 101 public void program(Console console) { console.println("Good morning, " + "what is your name?"); String name = console.readLine(); console.println(s"Good to meet you, $name!"); }
  • 30. BACK TO BASICS: JAVA 101 class LiveConsole implements Console { … } class TestConsole implements Console { … } // In production: program(new LiveConsole()); // In tests: program(new TestConsole());
  • 32. IO INTERFACES trait Console { def println(line: String): IO[Unit] val readLine: IO[String] }
  • 33. PURE PROGRAM WITH INTERFACE def program(c: Console) = for { _ <- c.println("Good morning, " + "what is your name?") name <- c.readLine _ <- c.println(s"Good to meet you, $name!") } yield ()
  • 34. POLYMORPHIC EFFECT trait Console[IO[_]] { def println(String line): IO[Unit] val readLine: IO[String] }
  • 35. MAKING IT EVEN MORE OBSCURE trait Console[F[_]] { def println(String line): F[Unit] val readLine: F[String] }
  • 36. THE GLORIOUS TAGLESS-FINAL TYPE CLASS trait Console[F[_]] { def println(String line): F[Unit] val readLine: F[String] } object Console { def apply[F[_]](implicit F: Console[F]) = F }
  • 37. EFFECT-POLYMORPHIC PROGRAMS def program[F[_]: Console: Monad] = for { _ <- Console[F].println( "Good morning, " + "what is your name?") name <- Console[F].readLine _ <- Console[F].println( s"Good to meet you, $name!") } yield ()
  • 38. TEST VS PRODUCTION EFFECTS case class TestIO[A](...) implicit val TestConsole = new Console[TestIO] { … } implicit val LiveConsole = new Console[IO] { … } // In production: program[IO] : IO[Unit] // In tests: program[TestIO] : TestIO[Unit]
  • 42. TAGLESS-FINAL IS PRETTY EASY! Functional Effects Parametric Polymorphism F
  • 43. TAGLESS-FINAL IS EASY-ISH! Functional Effects Parametric Polymorphism F[_] Higher-Kinded Types
  • 44. TAGLESS-FINAL ISN’T THAT HARD! Functional Effects Parametric Polymorphism trait Console[F[_]] { … } Higher-Kinded Types Type Classes
  • 45. TAGLESS-FINAL COULD BE MUCH HARDER! Functional Effects Parametric Polymorphism implicit val TestConsole = new Console[TestIO] { … } Higher-Kinded Types Type Classes Type Class Instances
  • 46. TAGLESS-FINAL IS SORT OF HARD! Functional Effects Parametric Polymorphism new Console[({type F[A] = State[TestData, A]})#F] { … } Higher-Kinded Types Type Classes Type Class Instances Partial Type Application
  • 47. OMG, TAGLESS-FINAL IS THE WORST!!! Functional Effects Parametric Polymorphism def program[F[_]: Monad: Console: Database] = ... Higher-Kinded Types Type Classes Type Class Instances Partial Type Application Monad Hierarchy
  • 48. TAGLESS-FINAL IS MANY THINGS EASY IS NOT ONE OF THEM
  • 49. ☠ TYPE CLASS ABUSE ☠ THE DARK SIDE OF TAGLESS-FINAL REAL TYPE CLASS Defines common structure across types through lawful operations, enabling abstraction. FAKE TYPE CLASS Defines a common interface across types through ad hoc polymorphism, enabling testing.
  • 50. ☠ TYPE CLASS ABUSE ☠ THE DARK SIDE OF TAGLESS-FINAL REAL TYPE CLASS Defines common structure across types through lawful operations, enabling abstraction. FAKE TYPE CLASS Defines a common interface across types through ad hoc polymorphism, enabling testing.
  • 51. ☠ BIG BANG INTRODUCTION ☠ THE DARK SIDE OF TAGLESS-FINAL def program[F[_]: Console: Monad] = for { _ <- Console[F].println( "Good morning, " + "what is your name?") name <- Console[F].readLine _ <- Console[F].println( s"Good to meet you, $name!") } yield ()
  • 52. ☠ TEDIOUS REPETITION ☠ THE DARK SIDE OF TAGLESS-FINAL def genFeed[F[_]: Monad: Logging: UserDatabase: ProfileDatabase: RedisCache: GeoIPService: AuthService: SessionManager: Localization: Config: EventQueue: Concurrent: Async: MetricsManager]: F[Feed] = ???
  • 53. ☠ STUBBORN REPETITION ☠ THE DARK SIDE OF TAGLESS-FINAL def genFeed[F[_]: Everything]: F[Feed] = ???
  • 54. ☠ COMPLETELY NON-INFERABLE ☠ THE DARK SIDE OF TAGLESS-FINAL def genFeed = ???
  • 55. ☠ FAKE PARAMETRIC GUARANTEES ☠ def innocent[F[_]: Monad]: F[Unit] = { def effect[A](a: => A): F[A] = Monad[F].point(()).map(_ => a) println("What guarantees?") effect(System.exit(42)) } THE DARK SIDE OF TAGLESS-FINAL
  • 56. THE DEATH OF TAGLESS-FINAL
  • 57. THE DEATH OF TAGLESS-FINAL
  • 59. ZIO is a zero-dependency Scala library for asynchronous and concurrent programming.
  • 61. BACK TO BASICS trait Console { def println(line: String): IO[Unit] val readLine: IO[String] }
  • 62. BACK TO BASICS def program(c: Console) = for { _ <- c.println("Good morning, " + "What is your name?") name <- c.readLine _ <- c.println(s"Good to meet you, $name!") } yield ()
  • 63. BACK TO BASICS def program(c: Console, p: Persistence) = for { _ <- c.println("Good morning, " + "what is your name?") name <- c.readLine _ <- p.savePreferences(name) _ <- c.println(s"Good to meet you, $name!") } yield ()
  • 64. BACK TO BASICS def program(s1: Service1, s2: Service2, s3: Service3, … sn: ServiceN) = for { a <- foo(s1, s9, s3)("localhost", 42) b <- bar(sn, s19, s3)(a, 1024) ... } yield z
  • 65. BACK TO BASICS def program(s1: Service1, s2: Service2, s3: Service3, … sn: ServiceN) = for { a <- foo(s1, s9, s3)("localhost", 42) b <- bar(sn, s19, s3)(a, 1024) ... } yield z
  • 66. THE MODULE PATTERN trait HasConsole { def console: HasConsole.Service } object HasConsole { trait Service { def println(line: String): IO[Unit] val readLine: IO[String] } }
  • 67. THE MODULE PATTERN trait HasConsole { def console: HasConsole.Service } object HasConsole { trait Service { def println(line: String): IO[Unit] val readLine: IO[String] } }
  • 68. THE MODULE PATTERN def program(s: HasConsole with HasPersistence) = for { _ <- s.console.println("What is your name?") name <- s.console.readLine _ <- s.persistence.savePreferences(name) _ <- s.console.println(s"Good to meet” + ” you, $name!") } yield ()
  • 69. THE MODULE PATTERN def program(s: HasService1 with … HasServiceN) = for { a <- foo(s)("localhost", 42) b <- bar(s)(a, 1024) ... } yield z
  • 70. THE READER MONAD case class Reader[-R, +A](provide: R => A) { self => def map[B](f: A => B) = flatMap(a => Reader.point(f(a))) def flatMap[R1 <: R, B](f: A => Reader[R1, B]) = Reader[R, B](r => f(self.provide(r)).provide(r)) } object Reader { def point[A](a: => A): Reader[Any, A] = Reader(_ => a) def environment[R]: Reader[R, R] = Reader(identity) }
  • 71. THE READER MONAD def program: Reader[HasService1 with ..., Unit] = for { a <- foo("localhost", 42) b <- bar(a, 1024) ... } yield z
  • 72. THE READER MONAD TRANSFORMER ReaderT[IO, R, A]
  • 73. THE READER MONAD TRANSFORMER ReaderT[IO, R, A] IO ReaderT
  • 77. ZIO ENVIRONMENT ZIO[R, E, A]* type UIO [ +A] = ZIO[Any, Nothing, A] type Task[ +A] = ZIO[Any, Throwable, A] type IO [+E, +A] = ZIO[Any, E, A] *
  • 78. ZIO ENVIRONMENT ZIO[R, E, A] Environment Type
  • 79. ZIO ENVIRONMENT ZIO[R, E, A] Failure Type
  • 80. ZIO ENVIRONMENT ZIO[R, E, A] Success Type
  • 82. ZIO ENVIRONMENT Might Fail with IOException ZIO[Console, IOException, Unit]
  • 83. ZIO ENVIRONMENT Might Succeed with Unit ZIO[Console, IOException, Unit]
  • 84. ZIO ENVIRONMENT: EXAMPLE val program: ZIO[Console with Persistence, IOException, Unit] = for { _ <- putStrLn("Good morning, what is your name?") name <- getStrLn _ <- savePreferences(name) _ <- putStrLn(s"Good to meet you, $name!") } yield ()
  • 85. ZIO ENVIRONMENT: CORE sealed trait ZIO[-R, +E, +A] { ... def provide(environment: R): ZIO[Any, E, A] = ... } object ZIO { def accessM[R, E, A](f: R => ZIO[R, E, A]): ZIO[R, E, A] = ... def access[R, E, A](f: R => A): ZIO[R, Nothing, A] = accessM(ZIO.succeed(_)) def environment[R]: ZIO[R, Nothing, R] = access(identity) }
  • 86. ZIO ENVIRONMENT: CORE sealed trait ZIO[-R, +E, +A] { ... def provide(environment: R): ZIO[Any, E, A] = ... } object ZIO { def accessM[R, E, A](f: R => ZIO[R, E, A]): ZIO[R, E, A] = ... def access[R, E, A](f: R => A): ZIO[R, Nothing, A] = accessM(ZIO.succeed(_)) def environment[R]: ZIO[R, Nothing, R] = access(identity) }
  • 87. ZIO ENVIRONMENT: CORE sealed trait ZIO[-R, +E, +A] { ... def provide(environment: R): ZIO[Any, E, A] = ... } object ZIO { def accessM[R, E, A](f: R => ZIO[R, E, A]): ZIO[R, E, A] = ... def access[R, E, A](f: R => A): ZIO[R, Nothing, A] = accessM(ZIO.succeed(_)) def environment[R]: ZIO[R, Nothing, R] = access(identity) }
  • 88. ZIO ENVIRONMENT: CORE sealed trait ZIO[-R, +E, +A] { ... def provide(environment: R): ZIO[Any, E, A] = ... } object ZIO { def accessM[R, E, A](f: R => ZIO[R, E, A]): ZIO[R, E, A] = ... def access[R, E, A](f: R => A): ZIO[R, Nothing, A] = accessM(ZIO.succeed(_)) def environment[R]: ZIO[R, Nothing, R] = access(identity) }
  • 89. ZIO ENVIRONMENT: TUTORIAL // Module (contains service) trait Console { def console: Console.Service }
  • 90. ZIO ENVIRONMENT: TUTORIAL object Console { // Service definition: trait Service { def println(line: String): ZIO[Any, Nothing, Unit] val readLine: ZIO[Any, IOException, String] } }
  • 91. ZIO ENVIRONMENT: TUTORIAL object ConsoleLive extends Console { val console = new Console.Service { def println(line: String): UIO[Unit] = ZIO.effectTotal(scala.io.StdIn.println(line)) val readLine: IO[IOException, String] = ZIO.effect(scala.io.StdIn.readLine()).refineOrDie { case e : IOException => e } } }
  • 92. ZIO ENVIRONMENT: TUTORIAL // Optional (but handy!) helpers: package object console { def println(line: String): ZIO[Console, Nothing, Unit] = ZIO.accessM(_.console println line) val readLine: ZIO[Console, IOException, String] = ZIO.accessM(_.console.readLine) }
  • 93. ZIO ENVIRONMENT: TUTORIAL val program: ZIO[Console, IOException, Unit] = for { _ <- putStrLn("Good morning, what is your name?") name <- getStrLn _ <- putStrLn(s"Good to meet you, $name!") } yield () DefaultRuntime.unsafeRun(program.provide(ConsoleLive))
  • 94. ZIO ENVIRONMENT: TUTORIAL object ConsoleTest extends Console { ... } DefaultRuntime.unsafeRun(program.provide(ConsoleTest))
  • 95. ZIO ENVIRONMENT: TUTORIAL val MyEnvironment: R = ... val MyRuntime: Runtime[R] = Runtime(MyEnvironment, PlatformLive) Your Own R Platform (thread pool, etc.)
  • 96. ZIO ENVIRONMENT: TEACHABLE trait Console { def console: Console.Service } object Console { trait Service { def println(line: String): ZIO[Any, Nothing, Unit] val readLine: ZIO[Any, IOException, String] } } object ConsoleLive extends Console.Service { def println(line: String) = ZIO.effectTotal(scala.io.StdIn.println(line)) val readLine = ZIO.effect(scala.io.StdIn.readLine()).refineOrDie(JustIOException) } Module
  • 97. ZIO ENVIRONMENT: TEACHABLE trait Console { def console: Console.Service } object Console { trait Service { def println(line: String): ZIO[Any, Nothing, Unit] val readLine: ZIO[Any, IOException, String] } } object ConsoleLive extends Console.Service { def println(line: String) = ZIO.effectTotal(scala.io.StdIn.println(line)) val readLine = ZIO.effect(scala.io.StdIn.readLine()).refineOrDie(JustIOException) } Service
  • 98. ZIO ENVIRONMENT: TEACHABLE trait Console { def console: Console.Service } object Console { trait Service { def println(line: String): ZIO[Any, Nothing, Unit] val readLine: ZIO[Any, IOException, String] } } object ConsoleLive extends Console.Service { def println(line: String) = ZIO.effectTotal(scala.io.StdIn.println(line)) val readLine = ZIO.effect(scala.io.StdIn.readLine()).refineOrDie(JustIOException) } Implementation
  • 99. ZIO ENVIRONMENT: COMPOSABLE trait Console { def console: Console.Service } trait Logging { def logging: Logging.Service } trait Persistence { def persistence: Persistence.Service } ... val program: ZIO[Console with Logging with Persistence, AppError, Unit] = ...
  • 101. ZIO ENVIRONMENT: FULLY INFERABLE val program = for { _ <- putStrLn("Good morning, what is your name?") name <- getStrLn _ <- savePreferences(name) _ <- log.debug("Saved $name to configuration") _ <- putStrLn(s"Good to meet you, $name!") } yield ()
  • 102. ZIO ENVIRONMENT: FULLY INFERABLE val program: ZIO[Console, Error, Unit] = ... ^^^^^^^ Found: Console Expected: Console with Persistence with Logging with Config with Auth
  • 103. ZIO ENVIRONMENT: CONCISE trait Console { def console: Console.Service } trait Logging { def logging: Logging.Service } trait Persistence { def persistence: Persistence.Service } ... type ProgramEnv = Console with Logging with Persistence val program: ZIO[ProgramEnv, AppError, Unit] = ...
  • 104. ZIO ENVIRONMENT: CONCISE trait Console { def console: Console.Service } trait Logging { def logging: Logging.Service } trait Persistence { def persistence: Persistence.Service } ... type Program[A] = ZIO[Console with Logging with Persistence, AppError, A] val program: Program[Unit] = ...
  • 105. ZIO ENVIRONMENT: MODULAR def fn1: ZIO[R1, E, A] = { def fn2: ZIO[R2, E, B] = ... val localEnvironment: R2 = ... val v1 = fn2.provide(localEnvironment) ... } val globalEnvironment: R1 = ... val v2 = fn1.provide(globalEnvironment) ...
  • 106. ZIO ENVIRONMENT: INCREMENTAL // Deeply nested code: val myCode: Task[Unit] = … for { ... result <- database.query(q) ... } yield ()
  • 107. ZIO ENVIRONMENT: INCREMENTAL type TaskDB[A] = ZIO[Database, Throwable, A] // Now fully testable! def myCodeV2: TaskDB[Unit] = … for { ... result <- database.query(q) ... } yield ()
  • 108. THE REANIMATION OF TAGLESS-FINAL
  • 109. THE REANIMATION OF TAGLESS-FINAL trait HasState[S] { def state: HasState.Service[S] } object HasState { trait Service[S] { def state: Ref[S] } }
  • 110. THE REANIMATION OF TAGLESS-FINAL implicit def MSZIO[S, R <: HasState[S], E]: MonadState[ZIO[R, E, ?], S] = new MonadState[ZIO[R, E, ?], S] { ... } ... def program[F[_]: MonadState[S, ?]]: F[Unit] = … program[ZIO[HasState[S], E]]
  • 111. THE REANIMATION OF TAGLESS-FINAL implicit def MSZIO[S, R <: HasState[S], E]: MonadState[ZIO[R, E, ?], S] = new MonadState[ZIO[R, E, ?], S] { ... } ... def program[F[_]: MonadState[MySt, ?]]: F[Unit] = … program[ZIO[HasState[MySt], Err]]
  • 113. THE (RE)RISING OF CAKE // Traditional MONOLITHIC cake trait MyModule extends CacheModule with LoggingModule with DatabaseModule with AuthModule { def refreshCache: Unit = ... def genFeed : Feed = ... def trace : Unit = ... }
  • 114. THE (RE)RISING OF CAKE // Next-generation MODULAR cake object MyFunctions { val refreshCache: ZIO[Cache, Error, Unit] = ... val genFeed: ZIO[Database with Auth, Error, Feed] = ... val trace: ZIO[Debug, Nothing, Unit] = ... }
  • 116. COMPARISON MATRIX Transformers Free Monads Eff Tagless Final Environmental Effects Composable ✔ ✔ ✔ ✔ ✔ Performance 𐄂 𐄂 𐄂 ✔ ✔ Reasoning Up to Discipline Up to Discipline Up to Discipline Up to Discipline Up to Discipline Easily Teachable 𐄂 ? ✔ 𐄂 ✔ Concision 𐄂 𐄂 𐄂 𐄂 ✔ Full Type Inference 𐄂 𐄂 𐄂 𐄂 ✔ Modularity ✔ ✔ ✔ 𐄂 ✔ Pinpoint Testability 𐄂 𐄂 𐄂 𐄂 ✔
  • 117. GETTING STARTED WITH ZIO ✨ github.com/scalaz/scalaz-zio ✨ gitter.im/scalaz/scalaz-zio ✨ scalaz.github.io/scalaz-zio
  • 118. Thank You! Any questions? Stalk me online at @jdegoes Follow Wiem online @wiemzin