SlideShare una empresa de Scribd logo
1 de 118
Descargar para leer sin conexión
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

Más contenido relacionado

La actualidad más candente

オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ増田 亨
 
A Scala Corrections Library
A Scala Corrections LibraryA Scala Corrections Library
A Scala Corrections LibraryPaul Phillips
 
Battle of the Stream Processing Titans – Flink versus RisingWave
Battle of the Stream Processing Titans – Flink versus RisingWaveBattle of the Stream Processing Titans – Flink versus RisingWave
Battle of the Stream Processing Titans – Flink versus RisingWaveYingjun Wu
 
CとGo -Go言語のご紹介-
CとGo -Go言語のご紹介-CとGo -Go言語のご紹介-
CとGo -Go言語のご紹介-Ryuji Iwata
 
Changelog Stream Processing with Apache Flink
Changelog Stream Processing with Apache FlinkChangelog Stream Processing with Apache Flink
Changelog Stream Processing with Apache FlinkFlink Forward
 
社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPI社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPIAkihiro Ikezoe
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and EffectsMartin Odersky
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Naoki Aoyama
 
ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』Yoshitaka Kawashima
 
GoF デザインパターン 2009
GoF デザインパターン 2009GoF デザインパターン 2009
GoF デザインパターン 2009miwarin
 
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリングUnityTechnologiesJapan002
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐりKazuyuki TAKASE
 
Use After Free 脆弱性攻撃を試す
Use After Free 脆弱性攻撃を試すUse After Free 脆弱性攻撃を試す
Use After Free 脆弱性攻撃を試すmonochrojazz
 
Laravelでfacadeを使わない開発
Laravelでfacadeを使わない開発Laravelでfacadeを使わない開発
Laravelでfacadeを使わない開発Kenjiro Kubota
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)Yoshitaka Kawashima
 
PHP7の内部実装から学ぶ性能改善テクニック
PHP7の内部実装から学ぶ性能改善テクニックPHP7の内部実装から学ぶ性能改善テクニック
PHP7の内部実装から学ぶ性能改善テクニックYoshio Hanawa
 
自己紹介LT(公開版)
自己紹介LT(公開版)自己紹介LT(公開版)
自己紹介LT(公開版)Ken Muryoi
 
こんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツールこんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツールdcubeio
 

La actualidad más candente (20)

オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ
 
A Scala Corrections Library
A Scala Corrections LibraryA Scala Corrections Library
A Scala Corrections Library
 
Battle of the Stream Processing Titans – Flink versus RisingWave
Battle of the Stream Processing Titans – Flink versus RisingWaveBattle of the Stream Processing Titans – Flink versus RisingWave
Battle of the Stream Processing Titans – Flink versus RisingWave
 
CとGo -Go言語のご紹介-
CとGo -Go言語のご紹介-CとGo -Go言語のご紹介-
CとGo -Go言語のご紹介-
 
Changelog Stream Processing with Apache Flink
Changelog Stream Processing with Apache FlinkChangelog Stream Processing with Apache Flink
Changelog Stream Processing with Apache Flink
 
社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPI社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPI
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術
 
ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』
 
GoF デザインパターン 2009
GoF デザインパターン 2009GoF デザインパターン 2009
GoF デザインパターン 2009
 
本当に怖いパフォーマンスが悪い実装 #phpcon2013
本当に怖いパフォーマンスが悪い実装 #phpcon2013本当に怖いパフォーマンスが悪い実装 #phpcon2013
本当に怖いパフォーマンスが悪い実装 #phpcon2013
 
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり
 
Use After Free 脆弱性攻撃を試す
Use After Free 脆弱性攻撃を試すUse After Free 脆弱性攻撃を試す
Use After Free 脆弱性攻撃を試す
 
React Redux AntD and Umi js
React Redux AntD and Umi jsReact Redux AntD and Umi js
React Redux AntD and Umi js
 
Laravelでfacadeを使わない開発
Laravelでfacadeを使わない開発Laravelでfacadeを使わない開発
Laravelでfacadeを使わない開発
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
 
PHP7の内部実装から学ぶ性能改善テクニック
PHP7の内部実装から学ぶ性能改善テクニックPHP7の内部実装から学ぶ性能改善テクニック
PHP7の内部実装から学ぶ性能改善テクニック
 
自己紹介LT(公開版)
自己紹介LT(公開版)自己紹介LT(公開版)
自己紹介LT(公開版)
 
こんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツールこんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツール
 

Similar a 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
 
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 ScalaWiem Zine Elabidine
 
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
 

Similar a 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
 

Más de 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
 
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
 
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
 

Más de 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!
 

Último

Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructureitnewsafrica
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Jeffrey Haguewood
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentMahmoud Rabie
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Nikki Chapple
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...Karmanjay Verma
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...amber724300
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Kaya Weers
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Mark Simos
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFMichael Gough
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfAarwolf Industries LLC
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 

Último (20)

Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career Development
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDF
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdf
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 

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