SlideShare a Scribd company logo
Plan
ZIO Library
Effects
Pure
Functions
Data
Structures
Built on ZIO
● ZIO is a zero-dependency Scala library for asynchronous and
concurrent programs using purely functional approach.
2
● Lets you build scalable, resilient, and reactive applications
that meet the needs of your business.
● Interaction with the real World
● Hard to reason about
● Hard to test
● Refactoring
● Programming without effects is useless
3
Effectful Program
{
Statement1
Statement2
Statement3
...
}
4
Effectful Program
Executing Describing
Execute effects Describe effects
Data
def main
unsafeRun
{
Statement1
Statement2
Statement3
}
for {
st1 <- Statement1
st2 <- Statement2
st3 <- Statement3
} yield ()
Effectful Program
Executing Describing
def main: Unit = {
println("Good morning, what is your name?")
val name = readLine()
println(s"Good to meet you, $name!")
}
val main = for {
_ <- putStrLn("Good morning, " +
"what is your name?")
name <- getStrLn
_ <- putStrLn(s"Good to meet you, $name!")
} yield ()
Effectful Program
Executing Describing
val main = for {
_ <- putStrLn("Good morning, " +
"what is your name?")
name <- getStrLn
_ <- putStrLn(s"Good to meet you, $name!")
} yield ()
def main: Unit = {
println("Good morning, what is your name?")
val name = readLine()
println(s"Good to meet you, $name!")
}
7
Pure function
Properties of pure functions:
● Total
● Deterministic
● Free of side effects
8
Pure function
def parseInt(s: String): Int = s.toInt
9
parseInt("Hello!")
[error] java.lang.NumberFormatException:
For input string: "Hello!"
def parseInt(s: String): Int = s.toInt
NOT TOTAL!
Pure function
10
Pure function
def parseInt(s: String): Option[Int]
=
Try(s.toInt).toOption
TOTAL
def parseInt(s: String): Int = s.toInt
11
Pure function
def addOne(x: Int): Int = Random.nextInt(x) + 1
12
def addOne(x: Int): Int = Random.nextInt(x) + 1 addOne(10)
> 4
addOne(10)
> 6
addOne(10)
> 2
NON DETERMINISTIC!
Pure function
13
Pure function
def addOne(x: Int): Int = x + 1
DETERMINISTIC
def addOne(x: Int): Int = Random.nextInt(x) + 1
14
Pure function
def makeCoffee(p: Payment, cc: CreditCard):
Coffee = {
val cup = new Coffee()
p.charge(cc, cup.price)
cup
}
15
SIDE EFFECT!
Pure function
def makeCoffee(p: Payment, cc: CreditCard):
Coffee = {
val cup = new Coffee()
p.charge(cc, cup.price)
cup
}
16
Pure function
FREE OF SIDE EFFECT
def makeCoffee(p: Payment, cc: CreditCard):
Coffee = {
val cup = new Coffee()
p.charge(cc, cup.price)
cup
}
final case class Charge(cc: CreditCard, price: Double)
def makeCoffee(cc: CreditCard): (Coffee, Charge) = {
val cup = new Coffee()
(cup, Charge(cc, cup.price))
}
17
Pure functions
def parseInt(s: String): Option[Int] =
Try(s.toInt).toOption
def addOne(x: Int): Int = x + 1
def makeCoffee(cc: CreditCard): (Coffee, Charge) =
{
val cup = new Coffee()
(cup, Charge(cc, cup.price))
}
Non-pure functions
def parseInt(s: String): Int = s.toInt
def addOne(x: Int): Int = Random.nextInt(x) + 1
def makeCoffee(withSugar: Option[Int],
p: Payment, cc: CreditCard): Coffee = {
val cup =
withSugar.fold(Coffee(0))(n => Coffee(n))
p.charge(cc, cup.price)
cup
}
def program(): = { } def program(): = { }
Pure function
Tour of ZIO
IO[E, A]
19
20
IO is an immutable data structure that describes an effectful
program that may:
● fail with an E
● run forever
● produce a single A
IO [E, A]
21
parseInt("hello") //fails with NumberFormatException
IO [E, A]
parseInt("1")
IO [E, A]
println("Hello!")
IO [E, A]
throw new Exception("error")
IO [E, A]
while(true) {}
IO [E, A]
trait IO[E, A] { self =>
def map[B](f: A => B): IO[E, B]
def flatMap[E, B](f0: A => IO[E, B]): IO[E, B]
...
}
object IO {
def fail[E](error: E): IO[E, Nothing] = ???
def succeed[A](a: A): IO[Nothing, A] = ???
...
}
IO [E, A]
IO describes the following effects:
● Errors
throw new Exception("error")
val failedIO: IO[Exception, Nothing] =
IO.fail(new Exception("error"))
IO [E, A]
IO describes the following effects:
● Errors
● Pure values
val number: Int= 1
val number: IO[Nothing, Int] = IO.succeed(1)
IO [E, A]
IO describes the following effects:
● Errors
● Pure Values
● Synchronous Effect
println("hello")
val toInt: IO[Nothing, Unit] =
IO.effectTotal(println("hello"))
IO [E, A]
IO describes the following effects:
● Errors
● Pure Values
● Synchronous Effect
"hello".toInt
val parseInt: IO[Throwable, Int] =
IO.effect("hello".toInt)
IO [E, A]
IO describes the following effects:
● Errors
● Pure Values
● Synchronous Effect
● Asynchronous Effects
Future(4)
IO.effectAsync[Nothing, Int](_(Completed(4)))
IO [E, A]
IO describes the following effects:
● Errors
● Pure Values
● Synchronous Effect
● Asynchronous Effects
● Concurrent Effects
val service: ExecutorService =
Executors.newFixedThreadPool(2)
service.submit(t1)
service.submit(t2)
def task(i: Int) = new Thread(
new Runnable {
def run() {
???
}
})
val task: IO[Throwable, (A, B)] = t1.zipPar(t2)
IO [E, A]
IO describes the following effects:
● Errors
● Pure Values
● Synchronous Effect
● Asynchronous Effects
● Concurrent Effects
● Resource Effects
val f: File = openFile()
try {
compute(f)
}
finally {
closeFile(f)
}
IO.bracket(openFile)(closeFile(_)) { file =>
compute(f)
}
IO [E, A]
IO describes the following effects:
● Errors
● Pure Values
● Synchronous Effect
● Asynchronous Effects
● Concurrent Effects
● Resource Effects
● Defects
Throw new FatalError
IO.die(FatalError)
IO [E, A]
IO describes the following effects:
● Errors
● Pure Values
● Synchronous Effect
● Asynchronous Effects
● Concurrent Effects
● Resource Effects
● Defects
● Contextual
def program[F[_]: Console: Monad] =
Console[F].println("Hello World")
val sayHello: ZIO[Console, Nothing, Unit] =
console.putStrLn("Hello World")
IO [E, A]
val parseInt: IO[String, Int] =
IO.effect("hello".toInt).catchSome{
case e: NumberFormatException => IO.fail(e.getMessage)
}
Error Handling
val parseInt: IO[String, Int] =
IO.effect("hello".toInt).catchAll(e => IO.fail(e.getMessage))
Error Handling
val value: IO[Nothing, Int] =
parseInt.either.map {
case Left(_) => -1
case Right(v) => v
}
Error Handling
val value: IO[Nothing, Int] =
parseInt.option.map {
case None => -1
case Some(v) => v
}
Error Handling
Error Handling
val value: IO[Nothing, Int] =
parseInt.fold(_ => -1, v => v)
Error Handling
val value: IO[Nothing, Int] =
parseInt.foldM(IO.succeed(-1), IO.succeed(_))
IO [E, A]
IO is interpreted by the IO runtime system into
effectful interactions with the external world.
● unsafeRun
● In your application’s main function (App
provides this functionality automatically).
def main(args: Array[String]): Unit =
println("Hello")
def main(args: Array[String]): Unit =
unsafeRun(IO.effect(println("Hello")))
Fiber
43
Fiber
Fiber is a lightweight version of thread to deal with
concurrency.
Fiber
JVM Thread
OS Thread
ZIO Fiber
Fiber Model
trait Fiber[E, A] {
def join: IO[E, A]
def interrupt: IO[Nothing, Exit[E, A]]
def poll: IO[Nothing, Option[Exit[E, A]]]
}
trait IO[E, A] {
def fork: IO[Nothing, Fiber[E, A]]
}
object IO {
def forkAll[E, A](as: Iterable[IO[E, A]): IO[Nothing, Fiber[E, List[A]]]
}
Fiber
def process: IO[Nothing, Fiber[Error, Nothing]] =
(for {
ev <- receive
_ <- ev match {
case NameChange(name) => updateNameDB(name)
case UserDeleted(id) => deleteUser(id)
}
_ <- LoggerIO.info(s"receive Event $ev")
} yield ()).forever.fork
Fiber
(for {
f <- createUser(usr).fork
...
io <- f.join
...
} yield ())
Fiber
def process: IO[Nothing, Fiber[Error, Nothing]] =
(for {
ev <- receive
_ <- ev match {
case NameChange(name) => updateNameDB(name)
case UserDeleted(id) => deleteUser(id)
}
_ <- LoggerIO.info(s"receive Event $ev")
} yield ()).forever.fork
Fiber
(for {
f <- IO.forkAll(users.map(usr => createUser(usr)))
...
_ <- f.join
...
} yield ()).foldM(
err => loggerIO.warn(err),
succ => LoggerIO.info(s"All users are created successfully"))
Fiber
for {
f <- readUsers.fork
...
v <- check(usr).foldM(_ => f.interrupt, createUser(usr))
...
} yield ()
Fiber
Parallelism &
concurrency
52
trait IO[E, A] {
def zipPar(that: IO[E, B]): IO[E, (A, B)]
}
Parallelism
object IO {
def collectAllPar(as: Iterable[IO[E, A]]): IO[E, List[A]]
def foreachPar[E, A, B](as: Iterable[A])(fn: A => IO[E, B]): IO[E, List[B]]
}
val profile: IO[Error, List[Information]] =
IO.collectAllPar(loadName(user) :: loadPicture(user) :: Nil)
val profileAndFriends: IO[Error, (UserInfo, List[Friend])] = infoUser.zipPar(friendList(user))
val newProfile: IO[Error, List[Profile]] = IO.foreachPar(readUser :: readImage)(createProfile)
Concurrency
trait IO[E, A] {
def race(that: IO[E, A]): IO[E, A]
}
Concurrency
object IO {
def raceAll(as: Iterable[IO[E, A]]): IO[E, A]
}
val availableService: IO[Error, Service] = IO.raceAll(services.map(_.await))
val fastTask: IO[Error, Task] = task1 race task2
Promise
56
Promise
● A Promise is a variable that can be set exactly once.
● Promises are used to build higher level concurrency
primitives.
Promise
By default the state of Promise is Pending, once it fails or succeeds the
state changes to Done.
`done`: completes the promise with the specified result.
A Promise is an asynchronous variable that
can be set only once.
Promise
trait Promise[E, A] {
def await: IO[E, A]
def poll: IO[Nothing, Option[IO[E, A]]]
def succeed(a: A): IO[Nothing, Boolean]
def fail(e: E): IO[Nothing, Boolean]
def interrupt: IO[Nothing, Boolean]
def done(io: IO[E, A]): IO[Nothing, Boolean]
...
}
object Promise {
def make[E, A]: IO[Nothing, Promise[E, A]] = ???
}
Chronometer
Chronometer
unsafeRun(
for {
chrono <- Chrono.start
_ <- chrono.run
_ <- chrono.stop.delay(duration)
} yield ()
)
Chronometer
case class Chrono(p: Promise[Nothing, Unit]) {
val run: IO[Nothing, Unit] =
for {
loop <- IO.foreach(1 to 60)(
i =>
console.putStrLn(s"$i").delay(1.second) *>
IO.succeed(i))
.forever.fork
_ <- p.await.flatMap(_ => loop.interrupt).fork
} yield ()
val stop: IO[Nothing, Boolean] = p.succeed(())
}
object Chrono {
def start: IO[Nothing, Chrono] = Promise.make[Nothing, Unit].map(Chrono(_))
}
Chronometer
unsafeRun(
for {
chrono <- Chrono.start
_ <- chrono.run
_ <- chrono.stop.delay(duration)
} yield ()
)
Ref
64
Ref
Ref[A] is a mutable reference to a value of type A.
All operations on a Ref are atomic and thread-safe, providing a reliable
foundation for synchronizing concurrent program.
Ref
object Ref {
def make[A](a: A): IO[Nothing, Ref[A]] = ???
}
trait Ref[A] {
def get: IO[Nothing, A]
def set(a: A): IO[Nothing, Unit]
def update(f: A => A): IO[Nothing, A]
def updateSome(pf: PartialFunction[A, A]): IO[Nothing, A]
def modify[B](f: A => (B, A)): IO[Nothing, B]
def modifySome[B](default: B)(pf: PartialFunction[A, (B, A)]): IO[Nothing, B]
}
Candy machine
Candy machine
Input
sealed trait Input
case object Coin extends Input
case object Turn extends Input
State
case class Machine(
locked: Boolean,
candies: Int,
coins: Int
)
Note: This example is from Functional Programming in Scala (the red book)
Candy machine
case class System (ref: Ref[Machine]) {
def simulate(inputs: List[Input]): IO[Nothing, (Int, Int)] =
for {
_ <- IO.foreach(inputs)(updateMachine)
machine <- ref.get
} yield (machine.coins, machine.candies)
…
}
Candy machine
def updateMachine(input: Input): IO[Nothing, Machine] =
refM.updateSome { machine =>
(input, machine) match {
case (Coin, Machine(true, candies, coins)) =>
Machine(false, candies, coins + 1)
case (Turn, Machine(false, candies, c)) =>
Machine(true, candies - 1, c)
}
Candy machine
case class System (refM: Ref[Machine]) {
def simulate(inputs: List[Input]): IO[Nothing, (Int, Int)] =
for {
_ <- IO.foreach(inputs)(updateMachine)
machine <- refM.get
} yield (machine.coins, machine.candies)
…
}
Schedule
72
Schedule
Schedule is an immutable value that describes
an effectful schedule, that decides to halt or
continue after some delay.
Schedule
● repeat actions
● retry actions in event of errors
Schedule
trait IO[E, A] {
def repeat[B](schedule: Schedule[A, B]): IO[E, B]
}
val refresh: IO[Nothing, Int] =
loadPage.repeat(Schedule.fixed(5.seconds))
Schedule
trait IO[E, A] {
def retry[B](policy: Schedule[E, B]): IO[E, A]
}
val request: IO[HttpError, Request] =
handleRequest.retry(Schedule.doWhile(_.code == 503))
Queue
77
Queue
Queue is an asynchronous queue which allows to add and
remove elements in First In First Out manner.
...
V6
V5
V4
V3
V2
V1
offer* take*
Producers Consumers
Queue
trait Queue[A] {
def take: IO[Nothing, A]
def takeAll: IO[Nothing, List[A]]
def takeUpTo(max: Int): IO[Nothing, List[A]]
def offer(a: A): IO[Nothing, Boolean]
def offerAll(as: Iterable[A]): IO[Nothing, Boolean]
}
object Queue {
def bounded[A](capacity: Int): IO[Nothing, Queue[A]]
def unbounded[A]: IO[Nothing, Queue[A]]
def sliding[A](capacity: Int): IO[Nothing, Queue[A]]
def dropping[A](capacity: Int): IO[Nothing, Queue[A]]
}
Backpressure
for {
queue <- Queue.unbounded[String]
v1 <- queue.take.fork
v2 <- queue.take.fork
take
take
Consumers
Backpressure
take
take
Consumers
for {
queue <- Queue.unbounded[String]
v1 <- queue.take.fork
v2 <- queue.take.fork
_ <- queue.offer("hello").fork
“hello”
Producers
Backpressure
take
take
Consumers
“hello”
for {
queue <- Queue.unbounded[String]
v1 <- queue.take.fork
v2 <- queue.take.fork
_ <- queue.offer("hello").fork
_ <- queue.offer("bye").fork
Producers
“bye”
Backpressure
take
take
Consumers
“bye”
“hello”
for {
queue <- Queue.unbounded[String]
v1 <- queue.take.fork
v2 <- queue.take.fork
_ <- queue.offer("hello").fork
_ <- queue.offer("bye").fork
Producers
Backpressure
take
Consumers
for {
queue <- Queue.unbounded[String]
v1 <- queue.take.fork
v2 <- queue.take.fork
_ <- queue.offer("hello").fork
_ <- queue.offer("bye").fork
Producers
“bye”
“hello”
Backpressure
Consumers
for {
queue <- Queue.unbounded[String]
v1 <- queue.take.fork
v2 <- queue.take.fork
_ <- queue.offer("hello").fork
_ <- queue.offer("bye").fork
} yield ()
Producers
“hello”
“bye”
Bounded Queue
A bounded Queue with capacity = 3
for {
queue <- Queue.bounded[String](3)
Bounded Queue
“b”
“c”
“a”
“d”
“b”
“c”
Producers
for {
queue <- Queue.bounded[String](3)
_ <- queue.offer("a").fork
_ <- queue.offer("b").fork
_ <- queue.offer("c").fork
_ <- queue.offer("d").fork
Bounded Queue
“c”
“b”
“a”
offer(“d”)
Producers
for {
queue <- Queue.bounded[String](3)
_ <- queue.offer("a").fork
_ <- queue.offer("b").fork
_ <- queue.offer("c").fork
_ <- queue.offer("d").fork
Bounded Queue
offer(“d”)
ConsumersProducers
for {
queue <- Queue.bounded[String](3)
_ <- queue.offer("a").fork
_ <- queue.offer("b").fork
_ <- queue.offer("c").fork
_ <- queue.offer("d").fork
v1 <- queue.take.fork
“c”
“b”
“a”
Bounded Queue
“c”
“b”
offer(“d”)
Consumers
“a”
Producers
for {
queue <- Queue.bounded[String](3)
_ <- queue.offer("a").fork
_ <- queue.offer("b").fork
_ <- queue.offer("c").fork
_ <- queue.offer("d").fork
v1 <- queue.take.fork
Bounded Queue
“d”
“c”
“b”
ConsumersProducers
for {
queue <- Queue.bounded[String](3)
_ <- queue.offer("a").fork
_ <- queue.offer("b").fork
_ <- queue.offer("c").fork
_ <- queue.offer("d").fork
v1 <- queue.take.fork
} yield ()
Sliding Queue
for {
queue <- Queue.sliding[String](3)
_ <- queue.offer("A") //(1)
} yield ()
Sliding Queue
for {
queue <- Queue.sliding[String](3)
_ <- queue.offer("A") //(1)
_ <- queue.offer("B") //(2)
} yield ()
Sliding Queue
for {
queue <- Queue.sliding[String](3)
_ <- queue.offer("A") //(1)
_ <- queue.offer("B") //(2)
_ <- queue.offer("C") //(3)
} yield ()
Sliding Queue
for {
queue <- Queue.sliding[String](3)
_ <- queue.offer("A") //(1)
_ <- queue.offer("B") //(2)
_ <- queue.offer("C") //(3)
_ <- queue.offer("D") //(4)
} yield ()
Sliding Queue
for {
queue <- Queue.sliding[String](3)
_ <- queue.offer("A") //(1)
_ <- queue.offer("B") //(2)
_ <- queue.offer("C") //(3)
_ <- queue.offer("D") //(4)
} yield ()
Dropping Queue
for {
queue <- Queue.dropping[String](3)
_ <- queue.offer("A") //(1)
} yield ()
Dropping Queue
for {
queue <- Queue.dropping[String](3)
_ <- queue.offer("A") //(1)
_ <- queue.offer("B") //(2)
} yield ()
Dropping Queue
for {
queue <- Queue.dropping[String](3)
_ <- queue.offer("A") //(1)
_ <- queue.offer("B") //(2)
_ <- queue.offer("C") //(3)
} yield ()
Dropping Queue
for {
queue <- Queue.dropping[String](3)
_ <- queue.offer("A") //(1)
_ <- queue.offer("B") //(2)
_ <- queue.offer("C") //(3)
_ <- queue.offer("D") //(4)
} yield ()
Dropping Queue
for {
queue <- Queue.dropping[String](3)
_ <- queue.offer("A") //(1)
_ <- queue.offer("B") //(2)
_ <- queue.offer("D") //(4)
} yield ()
Shutdown Queue
for {
queue <- Queue.bounded[String](1)
_ <- queue.offer("A").forever.fork
_ <- queue.take.forever.fork
_ <- queue.shutdown
} yield ()
Wrap UP
103
104
Include ZIO in your project by adding the following to your
build.sbt
libraryDependencies += "org.scalaz" %% "scalaz-zio" % "1.0-RC1"
github.com/scalaz/scalaz-zio
https://scalaz.github.io/scalaz-zio/
thanks!
Any questions?
You can find us at
@WiemZin
@Oleksandra_A

More Related Content

What's hot

A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIO
Jorge Vásquez
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022
Alexander Ioffe
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of Composition
Scott Wlaschin
 
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
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
Scott Wlaschin
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
Philip Schwarz
 
Monad Laws Must be Checked
Monad Laws Must be CheckedMonad Laws Must be Checked
Monad Laws Must be Checked
Philip Schwarz
 
Joy of scala
Joy of scalaJoy of scala
Joy of scala
Maxim Novak
 
The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of tests
Scott Wlaschin
 
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
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
Oliver Daff
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Jorge Vásquez
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Philip Schwarz
 
Zio in real world
Zio in real worldZio in real world
Zio in real world
Wiem Zine Elabidine
 
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
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
John De Goes
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)
Scott Wlaschin
 
Production-ready GraphQL with Caliban
Production-ready GraphQL with CalibanProduction-ready GraphQL with Caliban
Production-ready GraphQL with Caliban
Pierre Ricadat
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
Philip Schwarz
 

What's hot (20)

A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIO
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of Composition
 
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
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
Monad Laws Must be Checked
Monad Laws Must be CheckedMonad Laws Must be Checked
Monad Laws Must be Checked
 
Joy of scala
Joy of scalaJoy of scala
Joy of scala
 
The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of tests
 
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
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
 
Zio in real world
Zio in real worldZio in real world
Zio in real world
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)
 
Production-ready GraphQL with Caliban
Production-ready GraphQL with CalibanProduction-ready GraphQL with Caliban
Production-ready GraphQL with Caliban
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
 

Similar to ZIO: Powerful and Principled Functional Programming in Scala

ZIO Queue
ZIO QueueZIO Queue
Berlin meetup
Berlin meetupBerlin meetup
Berlin meetup
Wiem Zine Elabidine
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad
Fabernovel
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
scalaconfjp
 
Un dsl pour ma base de données
Un dsl pour ma base de donnéesUn dsl pour ma base de données
Un dsl pour ma base de données
Romain Lecomte
 
Implementing the IO Monad in Scala
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in Scala
Hermann Hueck
 
Zio from Home
Zio from Home Zio from Home
Zio from Home
Wiem Zine Elabidine
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risks
SeniorDevOnly
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
Adam L Barrett
 
Machine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting ConcernsMachine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting Concerns
saintiss
 
Monadologie
MonadologieMonadologie
Monadologie
league
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
Sigma Software
 
Future vs. Monix Task
Future vs. Monix TaskFuture vs. Monix Task
Future vs. Monix Task
Hermann Hueck
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
Michael Pirnat
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
Arturo Herrero
 
2016 gunma.web games-and-asm.js
2016 gunma.web games-and-asm.js2016 gunma.web games-and-asm.js
2016 gunma.web games-and-asm.js
Noritada Shimizu
 
Akka Futures and Akka Remoting
Akka Futures  and Akka RemotingAkka Futures  and Akka Remoting
Akka Futures and Akka Remoting
Knoldus Inc.
 
Introduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demoIntroduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demo
Muhammad Abdullah
 
Rethink programming: a functional approach
Rethink programming: a functional approachRethink programming: a functional approach
Rethink programming: a functional approach
Francesco Bruni
 

Similar to ZIO: Powerful and Principled Functional Programming in Scala (20)

ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
Berlin meetup
Berlin meetupBerlin meetup
Berlin meetup
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
Un dsl pour ma base de données
Un dsl pour ma base de donnéesUn dsl pour ma base de données
Un dsl pour ma base de données
 
Implementing the IO Monad in Scala
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in Scala
 
Zio from Home
Zio from Home Zio from Home
Zio from Home
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risks
 
Functional programming
Functional programmingFunctional programming
Functional programming
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
Machine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting ConcernsMachine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting Concerns
 
Monadologie
MonadologieMonadologie
Monadologie
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
 
Future vs. Monix Task
Future vs. Monix TaskFuture vs. Monix Task
Future vs. Monix Task
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
2016 gunma.web games-and-asm.js
2016 gunma.web games-and-asm.js2016 gunma.web games-and-asm.js
2016 gunma.web games-and-asm.js
 
Akka Futures and Akka Remoting
Akka Futures  and Akka RemotingAkka Futures  and Akka Remoting
Akka Futures and Akka Remoting
 
Introduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demoIntroduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demo
 
Rethink programming: a functional approach
Rethink programming: a functional approachRethink programming: a functional approach
Rethink programming: a functional approach
 

More from Wiem Zine Elabidine

New lambdas
New lambdasNew lambdas
New lambdas
Wiem Zine Elabidine
 
Friendly Functional Programming
Friendly Functional ProgrammingFriendly Functional Programming
Friendly Functional Programming
Wiem Zine Elabidine
 
Fiber supervision in ZIO
Fiber supervision in ZIOFiber supervision in ZIO
Fiber supervision in ZIO
Wiem Zine Elabidine
 
Flying Futures at the same sky can make the sun rise at midnight
Flying Futures at the same sky can make the sun rise at midnightFlying Futures at the same sky can make the sun rise at midnight
Flying Futures at the same sky can make the sun rise at midnight
Wiem Zine Elabidine
 
Pure Future
Pure FuturePure Future
Pure Future
Wiem Zine Elabidine
 
Zio in real world
Zio in real worldZio in real world
Zio in real world
Wiem Zine Elabidine
 

More from Wiem Zine Elabidine (6)

New lambdas
New lambdasNew lambdas
New lambdas
 
Friendly Functional Programming
Friendly Functional ProgrammingFriendly Functional Programming
Friendly Functional Programming
 
Fiber supervision in ZIO
Fiber supervision in ZIOFiber supervision in ZIO
Fiber supervision in ZIO
 
Flying Futures at the same sky can make the sun rise at midnight
Flying Futures at the same sky can make the sun rise at midnightFlying Futures at the same sky can make the sun rise at midnight
Flying Futures at the same sky can make the sun rise at midnight
 
Pure Future
Pure FuturePure Future
Pure Future
 
Zio in real world
Zio in real worldZio in real world
Zio in real world
 

Recently uploaded

Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Shahin Sheidaei
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
Strategies for Successful Data Migration Tools.pptx
Strategies for Successful Data Migration Tools.pptxStrategies for Successful Data Migration Tools.pptx
Strategies for Successful Data Migration Tools.pptx
varshanayak241
 
Why React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdfWhy React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdf
ayushiqss
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
XfilesPro
 
Advanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should KnowAdvanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should Know
Peter Caitens
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
A Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdfA Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdf
kalichargn70th171
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
Tendenci - The Open Source AMS (Association Management Software)
 

Recently uploaded (20)

Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
Strategies for Successful Data Migration Tools.pptx
Strategies for Successful Data Migration Tools.pptxStrategies for Successful Data Migration Tools.pptx
Strategies for Successful Data Migration Tools.pptx
 
Why React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdfWhy React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdf
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
 
Advanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should KnowAdvanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should Know
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
A Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdfA Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdf
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
 

ZIO: Powerful and Principled Functional Programming in Scala

  • 2. ● ZIO is a zero-dependency Scala library for asynchronous and concurrent programs using purely functional approach. 2 ● Lets you build scalable, resilient, and reactive applications that meet the needs of your business.
  • 3. ● Interaction with the real World ● Hard to reason about ● Hard to test ● Refactoring ● Programming without effects is useless 3 Effectful Program { Statement1 Statement2 Statement3 ... }
  • 4. 4 Effectful Program Executing Describing Execute effects Describe effects Data def main unsafeRun { Statement1 Statement2 Statement3 } for { st1 <- Statement1 st2 <- Statement2 st3 <- Statement3 } yield ()
  • 5. Effectful Program Executing Describing def main: Unit = { println("Good morning, what is your name?") val name = readLine() println(s"Good to meet you, $name!") } val main = for { _ <- putStrLn("Good morning, " + "what is your name?") name <- getStrLn _ <- putStrLn(s"Good to meet you, $name!") } yield ()
  • 6. Effectful Program Executing Describing val main = for { _ <- putStrLn("Good morning, " + "what is your name?") name <- getStrLn _ <- putStrLn(s"Good to meet you, $name!") } yield () def main: Unit = { println("Good morning, what is your name?") val name = readLine() println(s"Good to meet you, $name!") }
  • 7. 7 Pure function Properties of pure functions: ● Total ● Deterministic ● Free of side effects
  • 8. 8 Pure function def parseInt(s: String): Int = s.toInt
  • 9. 9 parseInt("Hello!") [error] java.lang.NumberFormatException: For input string: "Hello!" def parseInt(s: String): Int = s.toInt NOT TOTAL! Pure function
  • 10. 10 Pure function def parseInt(s: String): Option[Int] = Try(s.toInt).toOption TOTAL def parseInt(s: String): Int = s.toInt
  • 11. 11 Pure function def addOne(x: Int): Int = Random.nextInt(x) + 1
  • 12. 12 def addOne(x: Int): Int = Random.nextInt(x) + 1 addOne(10) > 4 addOne(10) > 6 addOne(10) > 2 NON DETERMINISTIC! Pure function
  • 13. 13 Pure function def addOne(x: Int): Int = x + 1 DETERMINISTIC def addOne(x: Int): Int = Random.nextInt(x) + 1
  • 14. 14 Pure function def makeCoffee(p: Payment, cc: CreditCard): Coffee = { val cup = new Coffee() p.charge(cc, cup.price) cup }
  • 15. 15 SIDE EFFECT! Pure function def makeCoffee(p: Payment, cc: CreditCard): Coffee = { val cup = new Coffee() p.charge(cc, cup.price) cup }
  • 16. 16 Pure function FREE OF SIDE EFFECT def makeCoffee(p: Payment, cc: CreditCard): Coffee = { val cup = new Coffee() p.charge(cc, cup.price) cup } final case class Charge(cc: CreditCard, price: Double) def makeCoffee(cc: CreditCard): (Coffee, Charge) = { val cup = new Coffee() (cup, Charge(cc, cup.price)) }
  • 17. 17 Pure functions def parseInt(s: String): Option[Int] = Try(s.toInt).toOption def addOne(x: Int): Int = x + 1 def makeCoffee(cc: CreditCard): (Coffee, Charge) = { val cup = new Coffee() (cup, Charge(cc, cup.price)) } Non-pure functions def parseInt(s: String): Int = s.toInt def addOne(x: Int): Int = Random.nextInt(x) + 1 def makeCoffee(withSugar: Option[Int], p: Payment, cc: CreditCard): Coffee = { val cup = withSugar.fold(Coffee(0))(n => Coffee(n)) p.charge(cc, cup.price) cup } def program(): = { } def program(): = { } Pure function
  • 20. 20 IO is an immutable data structure that describes an effectful program that may: ● fail with an E ● run forever ● produce a single A IO [E, A]
  • 21. 21 parseInt("hello") //fails with NumberFormatException IO [E, A]
  • 26. trait IO[E, A] { self => def map[B](f: A => B): IO[E, B] def flatMap[E, B](f0: A => IO[E, B]): IO[E, B] ... } object IO { def fail[E](error: E): IO[E, Nothing] = ??? def succeed[A](a: A): IO[Nothing, A] = ??? ... } IO [E, A]
  • 27. IO describes the following effects: ● Errors throw new Exception("error") val failedIO: IO[Exception, Nothing] = IO.fail(new Exception("error")) IO [E, A]
  • 28. IO describes the following effects: ● Errors ● Pure values val number: Int= 1 val number: IO[Nothing, Int] = IO.succeed(1) IO [E, A]
  • 29. IO describes the following effects: ● Errors ● Pure Values ● Synchronous Effect println("hello") val toInt: IO[Nothing, Unit] = IO.effectTotal(println("hello")) IO [E, A]
  • 30. IO describes the following effects: ● Errors ● Pure Values ● Synchronous Effect "hello".toInt val parseInt: IO[Throwable, Int] = IO.effect("hello".toInt) IO [E, A]
  • 31. IO describes the following effects: ● Errors ● Pure Values ● Synchronous Effect ● Asynchronous Effects Future(4) IO.effectAsync[Nothing, Int](_(Completed(4))) IO [E, A]
  • 32. IO describes the following effects: ● Errors ● Pure Values ● Synchronous Effect ● Asynchronous Effects ● Concurrent Effects val service: ExecutorService = Executors.newFixedThreadPool(2) service.submit(t1) service.submit(t2) def task(i: Int) = new Thread( new Runnable { def run() { ??? } }) val task: IO[Throwable, (A, B)] = t1.zipPar(t2) IO [E, A]
  • 33. IO describes the following effects: ● Errors ● Pure Values ● Synchronous Effect ● Asynchronous Effects ● Concurrent Effects ● Resource Effects val f: File = openFile() try { compute(f) } finally { closeFile(f) } IO.bracket(openFile)(closeFile(_)) { file => compute(f) } IO [E, A]
  • 34. IO describes the following effects: ● Errors ● Pure Values ● Synchronous Effect ● Asynchronous Effects ● Concurrent Effects ● Resource Effects ● Defects Throw new FatalError IO.die(FatalError) IO [E, A]
  • 35. IO describes the following effects: ● Errors ● Pure Values ● Synchronous Effect ● Asynchronous Effects ● Concurrent Effects ● Resource Effects ● Defects ● Contextual def program[F[_]: Console: Monad] = Console[F].println("Hello World") val sayHello: ZIO[Console, Nothing, Unit] = console.putStrLn("Hello World") IO [E, A]
  • 36. val parseInt: IO[String, Int] = IO.effect("hello".toInt).catchSome{ case e: NumberFormatException => IO.fail(e.getMessage) } Error Handling
  • 37. val parseInt: IO[String, Int] = IO.effect("hello".toInt).catchAll(e => IO.fail(e.getMessage)) Error Handling
  • 38. val value: IO[Nothing, Int] = parseInt.either.map { case Left(_) => -1 case Right(v) => v } Error Handling
  • 39. val value: IO[Nothing, Int] = parseInt.option.map { case None => -1 case Some(v) => v } Error Handling
  • 40. Error Handling val value: IO[Nothing, Int] = parseInt.fold(_ => -1, v => v)
  • 41. Error Handling val value: IO[Nothing, Int] = parseInt.foldM(IO.succeed(-1), IO.succeed(_))
  • 42. IO [E, A] IO is interpreted by the IO runtime system into effectful interactions with the external world. ● unsafeRun ● In your application’s main function (App provides this functionality automatically). def main(args: Array[String]): Unit = println("Hello") def main(args: Array[String]): Unit = unsafeRun(IO.effect(println("Hello")))
  • 44. Fiber Fiber is a lightweight version of thread to deal with concurrency.
  • 45. Fiber JVM Thread OS Thread ZIO Fiber Fiber Model
  • 46. trait Fiber[E, A] { def join: IO[E, A] def interrupt: IO[Nothing, Exit[E, A]] def poll: IO[Nothing, Option[Exit[E, A]]] } trait IO[E, A] { def fork: IO[Nothing, Fiber[E, A]] } object IO { def forkAll[E, A](as: Iterable[IO[E, A]): IO[Nothing, Fiber[E, List[A]]] } Fiber
  • 47. def process: IO[Nothing, Fiber[Error, Nothing]] = (for { ev <- receive _ <- ev match { case NameChange(name) => updateNameDB(name) case UserDeleted(id) => deleteUser(id) } _ <- LoggerIO.info(s"receive Event $ev") } yield ()).forever.fork Fiber
  • 48. (for { f <- createUser(usr).fork ... io <- f.join ... } yield ()) Fiber
  • 49. def process: IO[Nothing, Fiber[Error, Nothing]] = (for { ev <- receive _ <- ev match { case NameChange(name) => updateNameDB(name) case UserDeleted(id) => deleteUser(id) } _ <- LoggerIO.info(s"receive Event $ev") } yield ()).forever.fork Fiber
  • 50. (for { f <- IO.forkAll(users.map(usr => createUser(usr))) ... _ <- f.join ... } yield ()).foldM( err => loggerIO.warn(err), succ => LoggerIO.info(s"All users are created successfully")) Fiber
  • 51. for { f <- readUsers.fork ... v <- check(usr).foldM(_ => f.interrupt, createUser(usr)) ... } yield () Fiber
  • 53. trait IO[E, A] { def zipPar(that: IO[E, B]): IO[E, (A, B)] } Parallelism object IO { def collectAllPar(as: Iterable[IO[E, A]]): IO[E, List[A]] def foreachPar[E, A, B](as: Iterable[A])(fn: A => IO[E, B]): IO[E, List[B]] } val profile: IO[Error, List[Information]] = IO.collectAllPar(loadName(user) :: loadPicture(user) :: Nil) val profileAndFriends: IO[Error, (UserInfo, List[Friend])] = infoUser.zipPar(friendList(user)) val newProfile: IO[Error, List[Profile]] = IO.foreachPar(readUser :: readImage)(createProfile)
  • 55. trait IO[E, A] { def race(that: IO[E, A]): IO[E, A] } Concurrency object IO { def raceAll(as: Iterable[IO[E, A]]): IO[E, A] } val availableService: IO[Error, Service] = IO.raceAll(services.map(_.await)) val fastTask: IO[Error, Task] = task1 race task2
  • 57. Promise ● A Promise is a variable that can be set exactly once. ● Promises are used to build higher level concurrency primitives.
  • 58. Promise By default the state of Promise is Pending, once it fails or succeeds the state changes to Done. `done`: completes the promise with the specified result. A Promise is an asynchronous variable that can be set only once.
  • 59. Promise trait Promise[E, A] { def await: IO[E, A] def poll: IO[Nothing, Option[IO[E, A]]] def succeed(a: A): IO[Nothing, Boolean] def fail(e: E): IO[Nothing, Boolean] def interrupt: IO[Nothing, Boolean] def done(io: IO[E, A]): IO[Nothing, Boolean] ... } object Promise { def make[E, A]: IO[Nothing, Promise[E, A]] = ??? }
  • 61. Chronometer unsafeRun( for { chrono <- Chrono.start _ <- chrono.run _ <- chrono.stop.delay(duration) } yield () )
  • 62. Chronometer case class Chrono(p: Promise[Nothing, Unit]) { val run: IO[Nothing, Unit] = for { loop <- IO.foreach(1 to 60)( i => console.putStrLn(s"$i").delay(1.second) *> IO.succeed(i)) .forever.fork _ <- p.await.flatMap(_ => loop.interrupt).fork } yield () val stop: IO[Nothing, Boolean] = p.succeed(()) } object Chrono { def start: IO[Nothing, Chrono] = Promise.make[Nothing, Unit].map(Chrono(_)) }
  • 63. Chronometer unsafeRun( for { chrono <- Chrono.start _ <- chrono.run _ <- chrono.stop.delay(duration) } yield () )
  • 65. Ref Ref[A] is a mutable reference to a value of type A. All operations on a Ref are atomic and thread-safe, providing a reliable foundation for synchronizing concurrent program.
  • 66. Ref object Ref { def make[A](a: A): IO[Nothing, Ref[A]] = ??? } trait Ref[A] { def get: IO[Nothing, A] def set(a: A): IO[Nothing, Unit] def update(f: A => A): IO[Nothing, A] def updateSome(pf: PartialFunction[A, A]): IO[Nothing, A] def modify[B](f: A => (B, A)): IO[Nothing, B] def modifySome[B](default: B)(pf: PartialFunction[A, (B, A)]): IO[Nothing, B] }
  • 68. Candy machine Input sealed trait Input case object Coin extends Input case object Turn extends Input State case class Machine( locked: Boolean, candies: Int, coins: Int ) Note: This example is from Functional Programming in Scala (the red book)
  • 69. Candy machine case class System (ref: Ref[Machine]) { def simulate(inputs: List[Input]): IO[Nothing, (Int, Int)] = for { _ <- IO.foreach(inputs)(updateMachine) machine <- ref.get } yield (machine.coins, machine.candies) … }
  • 70. Candy machine def updateMachine(input: Input): IO[Nothing, Machine] = refM.updateSome { machine => (input, machine) match { case (Coin, Machine(true, candies, coins)) => Machine(false, candies, coins + 1) case (Turn, Machine(false, candies, c)) => Machine(true, candies - 1, c) }
  • 71. Candy machine case class System (refM: Ref[Machine]) { def simulate(inputs: List[Input]): IO[Nothing, (Int, Int)] = for { _ <- IO.foreach(inputs)(updateMachine) machine <- refM.get } yield (machine.coins, machine.candies) … }
  • 73. Schedule Schedule is an immutable value that describes an effectful schedule, that decides to halt or continue after some delay.
  • 74. Schedule ● repeat actions ● retry actions in event of errors
  • 75. Schedule trait IO[E, A] { def repeat[B](schedule: Schedule[A, B]): IO[E, B] } val refresh: IO[Nothing, Int] = loadPage.repeat(Schedule.fixed(5.seconds))
  • 76. Schedule trait IO[E, A] { def retry[B](policy: Schedule[E, B]): IO[E, A] } val request: IO[HttpError, Request] = handleRequest.retry(Schedule.doWhile(_.code == 503))
  • 78. Queue Queue is an asynchronous queue which allows to add and remove elements in First In First Out manner. ... V6 V5 V4 V3 V2 V1 offer* take* Producers Consumers
  • 79. Queue trait Queue[A] { def take: IO[Nothing, A] def takeAll: IO[Nothing, List[A]] def takeUpTo(max: Int): IO[Nothing, List[A]] def offer(a: A): IO[Nothing, Boolean] def offerAll(as: Iterable[A]): IO[Nothing, Boolean] } object Queue { def bounded[A](capacity: Int): IO[Nothing, Queue[A]] def unbounded[A]: IO[Nothing, Queue[A]] def sliding[A](capacity: Int): IO[Nothing, Queue[A]] def dropping[A](capacity: Int): IO[Nothing, Queue[A]] }
  • 80. Backpressure for { queue <- Queue.unbounded[String] v1 <- queue.take.fork v2 <- queue.take.fork take take Consumers
  • 81. Backpressure take take Consumers for { queue <- Queue.unbounded[String] v1 <- queue.take.fork v2 <- queue.take.fork _ <- queue.offer("hello").fork “hello” Producers
  • 82. Backpressure take take Consumers “hello” for { queue <- Queue.unbounded[String] v1 <- queue.take.fork v2 <- queue.take.fork _ <- queue.offer("hello").fork _ <- queue.offer("bye").fork Producers “bye”
  • 83. Backpressure take take Consumers “bye” “hello” for { queue <- Queue.unbounded[String] v1 <- queue.take.fork v2 <- queue.take.fork _ <- queue.offer("hello").fork _ <- queue.offer("bye").fork Producers
  • 84. Backpressure take Consumers for { queue <- Queue.unbounded[String] v1 <- queue.take.fork v2 <- queue.take.fork _ <- queue.offer("hello").fork _ <- queue.offer("bye").fork Producers “bye” “hello”
  • 85. Backpressure Consumers for { queue <- Queue.unbounded[String] v1 <- queue.take.fork v2 <- queue.take.fork _ <- queue.offer("hello").fork _ <- queue.offer("bye").fork } yield () Producers “hello” “bye”
  • 86. Bounded Queue A bounded Queue with capacity = 3 for { queue <- Queue.bounded[String](3)
  • 87. Bounded Queue “b” “c” “a” “d” “b” “c” Producers for { queue <- Queue.bounded[String](3) _ <- queue.offer("a").fork _ <- queue.offer("b").fork _ <- queue.offer("c").fork _ <- queue.offer("d").fork
  • 88. Bounded Queue “c” “b” “a” offer(“d”) Producers for { queue <- Queue.bounded[String](3) _ <- queue.offer("a").fork _ <- queue.offer("b").fork _ <- queue.offer("c").fork _ <- queue.offer("d").fork
  • 89. Bounded Queue offer(“d”) ConsumersProducers for { queue <- Queue.bounded[String](3) _ <- queue.offer("a").fork _ <- queue.offer("b").fork _ <- queue.offer("c").fork _ <- queue.offer("d").fork v1 <- queue.take.fork “c” “b” “a”
  • 90. Bounded Queue “c” “b” offer(“d”) Consumers “a” Producers for { queue <- Queue.bounded[String](3) _ <- queue.offer("a").fork _ <- queue.offer("b").fork _ <- queue.offer("c").fork _ <- queue.offer("d").fork v1 <- queue.take.fork
  • 91. Bounded Queue “d” “c” “b” ConsumersProducers for { queue <- Queue.bounded[String](3) _ <- queue.offer("a").fork _ <- queue.offer("b").fork _ <- queue.offer("c").fork _ <- queue.offer("d").fork v1 <- queue.take.fork } yield ()
  • 92. Sliding Queue for { queue <- Queue.sliding[String](3) _ <- queue.offer("A") //(1) } yield ()
  • 93. Sliding Queue for { queue <- Queue.sliding[String](3) _ <- queue.offer("A") //(1) _ <- queue.offer("B") //(2) } yield ()
  • 94. Sliding Queue for { queue <- Queue.sliding[String](3) _ <- queue.offer("A") //(1) _ <- queue.offer("B") //(2) _ <- queue.offer("C") //(3) } yield ()
  • 95. Sliding Queue for { queue <- Queue.sliding[String](3) _ <- queue.offer("A") //(1) _ <- queue.offer("B") //(2) _ <- queue.offer("C") //(3) _ <- queue.offer("D") //(4) } yield ()
  • 96. Sliding Queue for { queue <- Queue.sliding[String](3) _ <- queue.offer("A") //(1) _ <- queue.offer("B") //(2) _ <- queue.offer("C") //(3) _ <- queue.offer("D") //(4) } yield ()
  • 97. Dropping Queue for { queue <- Queue.dropping[String](3) _ <- queue.offer("A") //(1) } yield ()
  • 98. Dropping Queue for { queue <- Queue.dropping[String](3) _ <- queue.offer("A") //(1) _ <- queue.offer("B") //(2) } yield ()
  • 99. Dropping Queue for { queue <- Queue.dropping[String](3) _ <- queue.offer("A") //(1) _ <- queue.offer("B") //(2) _ <- queue.offer("C") //(3) } yield ()
  • 100. Dropping Queue for { queue <- Queue.dropping[String](3) _ <- queue.offer("A") //(1) _ <- queue.offer("B") //(2) _ <- queue.offer("C") //(3) _ <- queue.offer("D") //(4) } yield ()
  • 101. Dropping Queue for { queue <- Queue.dropping[String](3) _ <- queue.offer("A") //(1) _ <- queue.offer("B") //(2) _ <- queue.offer("D") //(4) } yield ()
  • 102. Shutdown Queue for { queue <- Queue.bounded[String](1) _ <- queue.offer("A").forever.fork _ <- queue.take.forever.fork _ <- queue.shutdown } yield ()
  • 104. 104 Include ZIO in your project by adding the following to your build.sbt libraryDependencies += "org.scalaz" %% "scalaz-zio" % "1.0-RC1"
  • 107. thanks! Any questions? You can find us at @WiemZin @Oleksandra_A

Editor's Notes

  1. The power of FP to change your way to do software
  2. <