SlideShare a Scribd company logo
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

More Related Content

What's hot

Spring Boot
Spring BootSpring Boot
Spring Boot
Pei-Tang Huang
 
07 java collection
07 java collection07 java collection
07 java collection
Abhishek Khune
 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in Scala
Vladimir Kostyukov
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
Martin Odersky
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
Arawn Park
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
Mario Fusco
 
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the CloudAmazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Noritaka Sekiyama
 
Java generics
Java genericsJava generics
Java generics
Hosein Zare
 
Tuning Apache Phoenix/HBase
Tuning Apache Phoenix/HBaseTuning Apache Phoenix/HBase
Tuning Apache Phoenix/HBase
Anil Gupta
 
Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21
Stamatis Zampetakis
 
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
HostedbyConfluent
 
[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka
[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka
[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka
NHN FORWARD
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
José Paumard
 
Cassandra Summit 2014: Novel Multi-Region Clusters — Cassandra Deployments Sp...
Cassandra Summit 2014: Novel Multi-Region Clusters — Cassandra Deployments Sp...Cassandra Summit 2014: Novel Multi-Region Clusters — Cassandra Deployments Sp...
Cassandra Summit 2014: Novel Multi-Region Clusters — Cassandra Deployments Sp...
DataStax Academy
 
Introduction to Spring Boot
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
Purbarun Chakrabarti
 
Apache Calcite: One planner fits all
Apache Calcite: One planner fits allApache Calcite: One planner fits all
Apache Calcite: One planner fits all
Julian Hyde
 
Spring boot introduction
Spring boot introductionSpring boot introduction
Spring boot introduction
Rasheed Waraich
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event Loop
Derek Willian Stavis
 
Spring Boot
Spring BootSpring Boot
Spring Boot
Jiayun Zhou
 
Materialized Views and Secondary Indexes in Scylla: They Are finally here!
Materialized Views and Secondary Indexes in Scylla: They Are finally here!Materialized Views and Secondary Indexes in Scylla: They Are finally here!
Materialized Views and Secondary Indexes in Scylla: They Are finally here!
ScyllaDB
 

What's hot (20)

Spring Boot
Spring BootSpring Boot
Spring Boot
 
07 java collection
07 java collection07 java collection
07 java collection
 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in Scala
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the CloudAmazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
 
Java generics
Java genericsJava generics
Java generics
 
Tuning Apache Phoenix/HBase
Tuning Apache Phoenix/HBaseTuning Apache Phoenix/HBase
Tuning Apache Phoenix/HBase
 
Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21
 
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
 
[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka
[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka
[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
 
Cassandra Summit 2014: Novel Multi-Region Clusters — Cassandra Deployments Sp...
Cassandra Summit 2014: Novel Multi-Region Clusters — Cassandra Deployments Sp...Cassandra Summit 2014: Novel Multi-Region Clusters — Cassandra Deployments Sp...
Cassandra Summit 2014: Novel Multi-Region Clusters — Cassandra Deployments Sp...
 
Introduction to Spring Boot
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
 
Apache Calcite: One planner fits all
Apache Calcite: One planner fits allApache Calcite: One planner fits all
Apache Calcite: One planner fits all
 
Spring boot introduction
Spring boot introductionSpring boot introduction
Spring boot introduction
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event Loop
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Materialized Views and Secondary Indexes in Scylla: They Are finally here!
Materialized Views and Secondary Indexes in Scylla: They Are finally here!Materialized Views and Secondary Indexes in Scylla: They Are finally here!
Materialized Views and Secondary Indexes in Scylla: They Are finally here!
 

Similar to The Death of Final Tagless

Berlin meetup
Berlin meetupBerlin meetup
Berlin meetup
Wiem Zine Elabidine
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To Scala
Innar Made
 
Scala Quick Introduction
Scala Quick IntroductionScala Quick Introduction
Scala Quick Introduction
Damian 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 Groovy
Arturo Herrero
 
Functional programming in Scala
Functional programming in ScalaFunctional programming in Scala
Functional programming in Scala
Damian Jureczko
 
Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009
David Pollak
 
ZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in Scala
Wiem Zine Elabidine
 
Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
Iran Entrepreneurship Association
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
Giordano Scalzo
 
Generic Functional Programming with Type Classes
Generic Functional Programming with Type ClassesGeneric Functional Programming with Type Classes
Generic Functional Programming with Type Classes
Tapio Rautonen
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
Tor Ivry
 
Thinking Functionally with JavaScript
Thinking Functionally with JavaScriptThinking Functionally with JavaScript
Thinking Functionally with JavaScript
Luis 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 Neckbeard
Kelsey Gilmore-Innis
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
Andrei Solntsev
 
Building a Functional Stream in Scala
Building a Functional Stream in ScalaBuilding a Functional Stream in Scala
Building a Functional Stream in Scala
Derek Wyatt
 

Similar to 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
 
ZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in Scala
 
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
 

More from John De Goes

Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
John De Goes
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
John De Goes
 
Error Management: Future vs ZIO
Error Management: Future vs ZIOError Management: Future vs ZIO
Error Management: Future vs ZIO
John 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: Rebirth
John De Goes
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: Rebirth
John De Goes
 
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
John De Goes
 
ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
John 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 2018
John De Goes
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New Game
John De Goes
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka Actors
John De Goes
 
Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional Architecture
John 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 System
John 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 & Analytics
John De Goes
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free Monads
John De Goes
 
Streams for (Co)Free!
Streams for (Co)Free!Streams for (Co)Free!
Streams for (Co)Free!
John De Goes
 
MTL Versus Free
MTL Versus FreeMTL Versus Free
MTL Versus 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 Future
John 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
 

More from 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 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 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!
 

Recently uploaded

GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
Abida Shariff
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Tobias Schneck
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
Fwdays
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 

Recently uploaded (20)

GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 

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