SlideShare ist ein Scribd-Unternehmen logo
1 von 68
Downloaden Sie, um offline zu lesen
1
Blazing Fast, Pure
Effects without
Monads
LambdaConf 2018
By John A. De Goes — @jdegoes
2
1991 1998 2018 - April
Eugenio Moggi John Hughes Flavio Brasil
F R O M M O N A D S T O A R R O W S
A brief history of effects leading to KleisliIO.
KleisliIO
2018 - June
Notions of
computation
and monads
Generalizing
monads to
arrows
TraneIO:
Arrows & tasks
in Scala
3
THE TRINITY OF FP
Total
Deterministic
Free of Side-effects
4
THE TRINITY OF FUNCTIONAL PROGRAMMING
Total
Deterministic
Free of Side-effects
f : A => B
a ∈ A ⇒ f(a) ∈ B
5
THE TRINITY OF FUNCTIONAL PROGRAMMING
Total
Deterministic
Free of Side-effects
def notTotal1(a: Int): String = null
def notTotal2(a: Int): String =
throw new Error(" ")
def notTotal3(a: Int): String = notTotal3(a)
6
THE TRINITY OF FUNCTIONAL PROGRAMMING
Total
Deterministic
Free of Side-effects
f : A => B
b1 = f(a) ∧ b2 = f(a) ⇒ b1 = b2
7
THE TRINITY OF FUNCTIONAL PROGRAMMING
Total
Deterministic
Free of Side-effects
def notDeterministic1(a: Int): String =
if (Math.random() > 0.5) "Hello"
else "Goodbye"
def notDeterministic2(a: Int): String =
scala.io.StdIn.readLine()
def notDeterministic3(a: Int): String =
(System.nanoTime() + a).toString
8
THE TRINITY OF FUNCTIONAL PROGRAMMING
Total
Deterministic
Free of Side-effects
f : A => B
f’s only computational effect is computing B
9
THE TRINITY OF FUNCTIONAL PROGRAMMING
Total
Deterministic
Free of Side-effects
def notEffectFree1(a: Int): String =
{ println("Hello"); a.toString }
def notEffectFree2(a: Int): String = {
val _ = scala.io.StdIn.readLine()
a.toString
}
def notEffectFree3(a: Int): String =
{ Logger.log(a); (a * a).toString }
10
THE RICHES OF PURITY
Type Reasoning
Equality Reasoning
11
Type Reasoning
Equality Reasoning
def foo1[A](a: A): A
def foo2[A](a: A, f: A => A): A
def foo3[A, B](f: (A => A) => B): B
THE RICHES OF PURITY
12
Type Reasoning
Equality Reasoning
def println(line: String): Unit
def readLine(): String
THE RICHES OF PURITY
13
Type Reasoning
Equality Reasoning
def f = (x: Int) => x * x
val b = f(a)
val c = b + b
// c = b + b
// c = f(a) + f(a)
// c = (a * a) + (a * a)
// c = 2 * a * a
THE RICHES OF PURITY
14
Type Reasoning
Equality Reasoning
def readLine = scala.io.StdIn.readLine()
val a = readLine
val b = a + a
// b = a + a
// b = readLine + readLine
// !?!?! readLine + readLine !=
// { val a = readLine; a + a }
THE RICHES OF PURITY
15
MONADIC EFFECTS
Effects Into Values
Values Into Effects
The Cost of Value Effects
16
17
EFFECTS INTO VALUES
def println(line: String): Unit
println
IO[Unit]
String
def println(line: String): IO[Unit]
18
EFFECTS INTO VALUES
IO[A]
Immutable value produced by the effect
Immutable value describing the effect
19
EFFECTS INTO VALUES
sealed trait IO[A] {
def map[B](f: A => B): IO[B] =
flatMap((a: A) => IO.point(f(a)))
def flatMap[B](f: A => IO[B]): IO[B] =
FlatMap(this, f)
}
object IO {
def point[A](a: A): IO[A] = Point(a)
}
final case class PrintLn(line: String) extends IO[Unit]
final case class ReadLine() extends IO[String]
final case class FlatMap[A, B](fa: IO[A], f: A => IO[B]) extends IO[B]
final case class Point[A](a: A) extends IO[A]
20
def readLine(): String
def println(line: String): Unit
val name = readLine()
println("Hello " + name + ", how are you?")
EFFECTS INTO VALUES
println
IO[Unit]
def readLine: IO[String]
def println(line: String): IO[Unit]
val program =
for {
name <- readLine
_ <- println("Hello " + name + ", how are you?")
} yield ()
readLine
IO[String]
String
Unit
21
VALUES INTO EFFECTS
def unsafePerformIO(io: IO[A]): A = io match {
case PrintLn(line) => println(line)
case ReadLine() => readLine()
case FlatMap(fa, f) =>
unsafePerformIO(f(unsafePerformIO(fa)))
case Point(a) => a
}
22
THE COST OF VALUE EFFECTS
println
F[Unit]
class SS {
for {
name <- readLine
_ <- println("Hello " + name +
", how are you?")
} yield ()
readLine
F[String]
String
Unit
23
THE COST OF VALUE EFFECTS
readLine.flatMap(name =>
printLn("Hello, " + name +
", how are you?"))
Allocations
Allocation
Megamorphic
Dispatch
24
THE COST OF VALUE EFFECTS
1 Statement in Procedural
Programming
4 Extra Allocations, 1 Extra
Megamorphic Dispatch in
Functional Programming
=
25
IO.sync {
App.main()
}
THE COST OF VALUE EFFECTS
Monolith Composed
Pure Values
26
THE COST OF VALUE EFFECTS
Future
27
KLEISLI EFFECTS
Effects Into Values
Values Into Effects
The Cost of Value Effects
28
29
EFFECTS INTO VALUES
def println(line: String): Unit
println
FunctionIO[String, Unit]
val println: FunctionIO[String, Unit]
30
EFFECTS INTO VALUES
FunctionIO[A, B]
Immutable input value to the function
Immutable value describing the effectful function
Immutable output value from the function
31
EFFECTS INTO VALUES
final case class FunctionIO[A, B](apply0: A => IO[B])
extends (A => IO[B]) {
def apply(a: A): IO[B] = apply0(a)
def andThen[C](f: FunctionIO[B, C]): FunctionIO[A, C] =
FunctionIO(a => apply(a).flatMap(f.apply))
}
object FunctionIO {
def lift[A, B](f: A => B): FunctionIO[A, B] =
FunctionIO(IO.point.compose(f))
}
32
def readLine(): String
def println(line: String): Unit
val name = readLine()
println("Hello " + name + ", how are you?")
EFFECTS INTO VALUES
val readLine: FunctionIO[Unit, String]
val println: FunctionIO[String, Unit]
val program =
readLine
.andThen(lift((name: String) => "Hello, " + name +
", how are you?"))
.andThen(println)
readLine
FunctionIO[Unit, String]
<anonymous>
FunctionIO[String,String]
println
FunctionIO[String, Unit]
33
VALUES INTO EFFECTS
val program: FunctionIO[Unit, Unit]
unsafePerformIO(program())
34
THE COST OF EFFECT VALUES
readLine.andThen(lift((name: String) =>
"Hello, " + name + ", how are you?"))
.andThen(println)
readLine
FunctionIO[Unit, String]
<anonymous>
FunctionIO[String,String]
println
FunctionIO[String, Unit]
35
Megamorphic
Dispatches
final case class FunctionIO[A, B](apply: A => IO[B])
THE COST OF EFFECT VALUES
readLine.andThen(println)
Allocations Allocations
36
THE COST OF EFFECT VALUES
1 Statement in Procedural
Programming
6 Extra Allocations, 3 Extra
Megamorphic Dispatches in
Functional Programming
=
37
THE PROMISE OF KLEISLIIO
sealed trait FunctionIO[A, B] extends (A => IO[B]) { ... }
final class Pure[A, B](val apply0: A => IO[B])
extends FunctionIO[A, B] {
def apply(a: A): IO[B] = apply0(a)
}
final class Impure[A, B](val apply0: A => B)
extends FunctionIO[A, B] {
def apply(a: A): IO[B] = IO.point(apply0(a))
}
val readLine: FunctionIO[Unit, String] =
new Impure(_ => scala.io.StdIn.readLine())
val printLn: FunctionIO[String, Unit] = new Impure(println)
38
THE PROMISE OF KLEISLIIO
class Impure[A, B](val apply0: A => B)
1 Invocation in Procedural
Programming
0 Extra Allocations,
1 Extra Dispatch in
Functional Programming
=
39
KLEISLIIO
Running KleisliIO
Constructing KleisliIO
Composing KleisliIO
Introducing KleisliIO
Optimizing KleisliIO
Testing KleisliIO
40
KLEISLIIO
sealed trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... }
object KleisliIO {
class KleisliIOError[E](error: E) extends Throwable {
def unsafeCoerce[E2] = error.asInstanceOf[E2]
}
class Pure[E, A, B](apply0: A => IO[E, B]) extends KleisliIO[E, A, B] {
override final def apply(a: A): IO[E, B] = apply0(a)
}
class Impure[E, A, B](val apply0: A => B) extends KleisliIO[E, A, B] {
override final def apply(a: A): IO[E, B] =
IO.suspend {
try IO.now[E, B](apply0(a))
catch {
case e: KleisliIOError[_] => IO.fail[E, B](e.unsafeCoerce[E])
}
}
}
...
}
41
RUNNING KLEISLIIO
val printLn: KleisliIO[IOException, String, Unit]
printLn("Hello, world!") // IO[IOException, Unit]
42
CONSTRUCTING PURE KLEISLIIO
object KleisliIO {
...
def pure[E, A, B](f: A => IO[E, B]):
KleisliIO[E, A, B] = ???
...
}
val printLn: KleisliIO[Void, String, Unit] =
KleisliIO.pure((a: String) => IO.sync(println(a)))
43
CONSTRUCTING IMPURE KLEISLIIO
object KleisliIO {
...
def impure[E, A, B](catcher: PartialFunction[Throwable, E])(f: A => B)
...
}
val IOExceptions: PartialFunction[Throwable, IOException] = {
case io : IOException => io
}
val printLn: KleisliIO[Void, String, Unit] =
KleisliIO.impure(IOExceptions)(println)
44
CONSTRUCTING IMPURE KLEISLIIO
object KleisliIO {
...
def impureVoid[A, B](f: A => B): KleisliIO[Void, A, B] = ???
...
}
val printLn: KleisliIO[Void, String, Unit] = KleisliIO.impureVoid(println)
45
CONSTRUCTING KLEISLIIO
object KleisliIO {
...
def identity[E, A]: KleisliIO[E, A, A] = ???
...
}
A A
KleisliIO.identity[Void, Int](1) // IO.point(1)
46
COMPOSING KLEISLIIO
trait KleisliIO[E, A, B] extends (A => IO[E, B])
{
...
def >>>[C](that: KleisliIO[E, B, C]):
KleisliIO[E, A, C] = ???
...
}
...
A B C
A C
readLine >>> printLn
47
COMPOSING KLEISLIIO
A
B
C
(B, C) => D
A D
trait KleisliIO[E, A, B] extends (A => IO[E, B]) {
...
def zipWith[C, D](that: KleisliIO[E, A, C])(f: (B, C) => D):
KleisliIO[E, A, D] = ???
...
}
readLine.zipWith(readLine)((l1, l2) => l1 + l2)
48
COMPOSING KLEISLIIO
trait KleisliIO[E, A, B] extends (A => IO[E, B]) {
...
def &&&[C]( that: KleisliIO[E, A, C]):
KleisliIO[E, A, (B, C)] = ???
...
}
A
B
C
A (B,C)
readLine &&& readLine
49
COMPOSING KLEISLIIO
trait KleisliIO[E, A, B] extends (A => IO[E, B]) {
...
def |||[C](that: KleisliIO[E, C, B]):
KleisliIO[E, Either[A, C], B]
...
}
A
B
C
Either[A, C] D
(fancyPrintLn |||
standardPrintLn)(Left("Fancied!"))
50
COMPOSING KLEISLIIO
trait KleisliIO[E, A, B] extends (A => IO[E, B]) {
...
def first: KleisliIO[E, A, (B, A)] =
this &&& KleisliIO.identity[E, A]
...
}
A B
A (B, A)
readLine >>> printLn.first // (Unit, String)
51
COMPOSING KLEISLIIO
trait KleisliIO[E, A, B] extends (A => IO[E, B]) {
...
def second: KleisliIO[E, A, (A, B)] =
KleisliIO.identity[E, A] &&& this
...
}
A B
A (A, B)
readLine >>> printLn.second // (String, Unit)
52
COMPOSING KLEISLIIO
trait KleisliIO[E, A, B] extends (A => IO[E, B]) {
...
def left[C]:
KleisliIO[E, Either[A, C], Either[B, C]] = ???
...
}
Either[A, C] Either[B, C]
A B
printLn.left[String]( Left("Hello")) //
Left[Unit]
53
COMPOSING KLEISLIIO
trait KleisliIO[E, A, B] extends (A => IO[E, B]) {
...
def right[C]:
KleisliIO[E, Either[A, C], Either[B, C]] = ???
...
}
Either[A, C] Either[B, C]
A B
printLn.right[String]( Right("Hello")) // Right[Unit]
54
COMPOSING KLEISLIIO
trait KleisliIO[E, A, B] extends (A => IO[E, B])
{
...
def asEffect: KleisliIO[E, A, A] =
self.first >>> KleisliIO._2
...
}
A A
B
printLn.asEffect // String
55
COMPOSING KLEISLIIO
object KleisliIO {
...
def test[E, A](cond: KleisliIO[E, A, Boolean]):
KleisliIO[E, A, Either[A, A]] = ???
...
}
test(KleisliIO.lift(_ > 2))(4) // IO[Void, Either[Int,
Int]]
cond
A Bool
A Either[A, A]
Right(a)Left(a)
56
COMPOSING KLEISLIIO
object KleisliIO {
...
def ifThenElse[E, A, B](cond : KleisliIO[E, A, Boolean])
(then0: KleisliIO[E, A, B])(else0: KleisliIO[E, A, B]):
KleisliIO[E, A, B] =
test[E, A](cond) >>> (then0 ||| else0)
...
}
ifThenElse(KleisliIO.lift(_ == "John"))(printLn)(const(()))
A B
else0 then0
A BA B
cond
A Bool
57
COMPOSING KLEISLIIO
object KleisliIO {
...
def whileDo[E, A](check: KleisliIO[E, A, Boolean])
(body : KleisliIO[E, A, A]): KleisliIO[E, A, A] = ???
...
}
A A
A Boolean
A Abody
check
readLine >>> whileDo(lift(_ != “John”)) {
KleisliIO.point(“Wrong name”) >>> printLn >>> readLine
}
58
OPTIMIZING KLEISLIIO
final def compose[E, A, B, C](second: KleisliIO[E, B, C], first: KleisliIO[E, A, B]):
KleisliIO[E, A, C] =
(second, first) match {
case (second: Impure[_, _, _], first: Impure[_, _, _]) =>
new Impure(second.apply0.compose(first.apply0))
case _ =>
new Pure((a: A) => first(a).flatMap(second))
}
59
OPTIMIZING KLEISLIIO
final def ifThenElse[E, A, B](cond: KleisliIO[E, A, Boolean])
(then0: KleisliIO[E, A, B])(else0: KleisliIO[E, A, B]): KleisliIO[E, A, B] =
(cond, then0, else0) match {
case (cond: Impure[_, _, _], then0: Impure[_, _, _], else0: Impure[_, _, _]) =>
new Impure[E, A, B](a => if (cond.apply0(a)) then0.apply0(a) else else0.apply0(a))
case _ => test[E, A](cond) >>> (then0 ||| else0)
}
60
OPTIMIZING KLEISLIIO
final def whileDo[E, A](check: KleisliIO[E, A, Boolean])(body: KleisliIO[E, A, A]): KleisliIO[E, A, A] =
(check, body) match {
case (check: Impure[_, _, _], body: Impure[_, _, _]) =>
new Impure[E, A, A]({ (a0: A) =>
val cond = check.apply0
val update = body.apply0
var a = a0
while (cond(a)) { a = update(a) }
a
})
case _ =>
lazy val loop: KleisliIO[E, A, A] =
KleisliIO.pure((a: A) =>
check(a).flatMap((b: Boolean) =>
if (b) body(a).flatMap(loop) else IO.now(a)))
loop
}
61
TESTING KLEISLIIO - ARRAY FILL
Output: An array filled with 10,000 elements in increasing order.
62
TESTING KLEISLIIO - ARRAY FILL
def arrayFill(array: Array[Int]): KleisliIO[Void, Int] = {
val condition = KleisliIO.lift(i => i < array.length)
val update = KleisliIO.impureVoid{ i =>
array.update(i, i); i + 1 }
KleisliIO.whileDo(condition)(update)
}
def arrayFill(array: Array[Int])(i: Int): IO[Unit] =
if (i >= array.length) IO.unit
else IO(array.update(i, i)).flatMap(_ => arrayFill(array)(i + 1))
KleisliIO Array Fill Monadic Array Fill
63
TESTING KLEISLIIO - ARRAY FILL
7958.946 ops/s
3622.744 ops/s
3689.406 ops/s
Array Fill
2.18x Faster!
64
TESTING KLEISLIIO - BUBBLE SORT
Input: Array of 10000 element with reversed order
Output: bubbleSort(array)
bubbleSort(array):
i <- 1 to 10000
j <- i + 1 to 9999
lessThanEqual = array(i) <= array(j)
if (!lessThanEqual) swap(array, i, j)
65
TESTING KLEISLIIO - BUBBLE SORT
val sort: KleisliIO[Void, Int, Unit] =
KleisliIO
.whileDo(outerLoopCheck)(
innerLoopStart >>>
KleisliIO.whileDo(innerLoopCheck)(
extractIJIndexValue >>>
KleisliIO.ifNotThen(lessThanEqual)(swapIJ) >>>
extractIJAndIncrementJ
) >>>
extractIAndIncrementI
)
sort(0)
def outerLoop(i: Int): IO[Unit] =
if (i >= array.length - 1) IO.unit
else innerLoop(i, i + 1).flatMap(_ => outerLoop(i + 1))
def innerLoop(i: Int, j: Int): IO[Unit] =
if (j >= array.length) IO.unit
else IO((array(i), array(j))).flatMap {
case (ia, ja) =>
val maybeSwap = if (lessThanEqual0(ia, ja)) IO.unit
else swapIJ(i, ia, j, ja)
maybeSwap.flatMap(_ => innerLoop(i, j + 1))
}
outerLoop(0)
KleisliIO Bubble sort Monadic Bubble sort
66
TESTING KLEISLIIO - BUBBLE SORT
58.811 ops/s
41.545 ops/s
33.229 ops/s
1.57x Faster!
Bubble Sort
67
W H E R E F R O M H E R E
A brief roadmap for KleisliIO.
?
Infinite
Composition
Recursion
Combinator
Low-Cost
Propagation
68
THANK YOU!
Thanks to the staff, volunteers, and speakers of
LambdaConf, and to Wiem Zine El Abidine for
help with the development and
implementation of KleisliIO.
Follow me @jdegoes
Follow Wiem @wiemzin
Join Scalaz at gitter.im/scalaz/scalaz

Weitere ähnliche Inhalte

Was ist angesagt?

The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...Philip Schwarz
 
Left and Right Folds - Comparison of a mathematical definition and a programm...
Left and Right Folds- Comparison of a mathematical definition and a programm...Left and Right Folds- Comparison of a mathematical definition and a programm...
Left and Right Folds - Comparison of a mathematical definition and a programm...Philip Schwarz
 
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 testsScott 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 CatsPhilip Schwarz
 
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
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Scott Wlaschin
 
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
 
Functors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In ScalaFunctors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In ScalaKnoldus Inc.
 
Taking your side effects aside
Taking your side effects asideTaking your side effects aside
Taking your side effects aside💡 Tomasz Kogut
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programmingScott Wlaschin
 
Hot C++: Rvalue References And Move Semantics
Hot C++: Rvalue References And Move SemanticsHot C++: Rvalue References And Move Semantics
Hot C++: Rvalue References And Move SemanticsAndrey Upadyshev
 
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 @FunctionalWorldJorge Vásquez
 
Monad as functor with pair of natural transformations
Monad as functor with pair of natural transformationsMonad as functor with pair of natural transformations
Monad as functor with pair of natural transformationsPhilip Schwarz
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022Alexander Ioffe
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Philip Schwarz
 
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021Natan Silnitsky
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Philip Schwarz
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type ClassesJohn De Goes
 

Was ist angesagt? (20)

The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
 
Left and Right Folds - Comparison of a mathematical definition and a programm...
Left and Right Folds- Comparison of a mathematical definition and a programm...Left and Right Folds- Comparison of a mathematical definition and a programm...
Left and Right Folds - Comparison of a mathematical definition and a programm...
 
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 Queue
ZIO QueueZIO Queue
ZIO Queue
 
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
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013
 
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...
 
Functors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In ScalaFunctors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In Scala
 
Taking your side effects aside
Taking your side effects asideTaking your side effects aside
Taking your side effects aside
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programming
 
Hot C++: Rvalue References And Move Semantics
Hot C++: Rvalue References And Move SemanticsHot C++: Rvalue References And Move Semantics
Hot C++: Rvalue References And Move Semantics
 
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
 
Monad as functor with pair of natural transformations
Monad as functor with pair of natural transformationsMonad as functor with pair of natural transformations
Monad as functor with pair of natural transformations
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
 
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
 

Ähnlich wie Blazing Fast, Pure Effects without Monads — LambdaConf 2018

Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'Philip Schwarz
 
Functions Practice Sheet.docx
Functions Practice Sheet.docxFunctions Practice Sheet.docx
Functions Practice Sheet.docxSwatiMishra364461
 
Scalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with ScalaScalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with ScalaDaniel Sebban
 
Scala Functional Patterns
Scala Functional PatternsScala Functional Patterns
Scala Functional Patternsleague
 
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
 
Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2Hang Zhao
 
GoLightly: Building VM-Based Language Runtimes with Google Go
GoLightly: Building VM-Based Language Runtimes with Google GoGoLightly: Building VM-Based Language Runtimes with Google Go
GoLightly: Building VM-Based Language Runtimes with Google GoEleanor McHugh
 
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éesRomain Lecomte
 
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
 
Python Unit 3 - Control Flow and Functions
Python Unit 3 - Control Flow and FunctionsPython Unit 3 - Control Flow and Functions
Python Unit 3 - Control Flow and FunctionsDhivyaSubramaniyam
 
Rethink programming: a functional approach
Rethink programming: a functional approachRethink programming: a functional approach
Rethink programming: a functional approachFrancesco Bruni
 
Functional IO and Effects
Functional IO and EffectsFunctional IO and Effects
Functional IO and EffectsDylan Forciea
 
Basic_analysis.ppt
Basic_analysis.pptBasic_analysis.ppt
Basic_analysis.pptSoumyaJ3
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Mario Fusco
 

Ähnlich wie Blazing Fast, Pure Effects without Monads — LambdaConf 2018 (20)

Berlin meetup
Berlin meetupBerlin meetup
Berlin meetup
 
Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'Simple IO Monad in 'Functional Programming in Scala'
Simple IO Monad in 'Functional Programming in Scala'
 
Functions Practice Sheet.docx
Functions Practice Sheet.docxFunctions Practice Sheet.docx
Functions Practice Sheet.docx
 
Scalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with ScalaScalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with Scala
 
Scala Functional Patterns
Scala Functional PatternsScala Functional Patterns
Scala Functional Patterns
 
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
 
Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2
 
GoLightly: Building VM-Based Language Runtimes with Google Go
GoLightly: Building VM-Based Language Runtimes with Google GoGoLightly: Building VM-Based Language Runtimes with Google Go
GoLightly: Building VM-Based Language Runtimes with Google Go
 
ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
Functional programming
Functional programmingFunctional programming
Functional programming
 
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
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free Monads
 
Python Unit 3 - Control Flow and Functions
Python Unit 3 - Control Flow and FunctionsPython Unit 3 - Control Flow and Functions
Python Unit 3 - Control Flow and Functions
 
chapter1.ppt
chapter1.pptchapter1.ppt
chapter1.ppt
 
chapter1.ppt
chapter1.pptchapter1.ppt
chapter1.ppt
 
Rethink programming: a functional approach
Rethink programming: a functional approachRethink programming: a functional approach
Rethink programming: a functional approach
 
Go a crash course
Go   a crash courseGo   a crash course
Go a crash course
 
Functional IO and Effects
Functional IO and EffectsFunctional IO and Effects
Functional IO and Effects
 
Basic_analysis.ppt
Basic_analysis.pptBasic_analysis.ppt
Basic_analysis.ppt
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 

Mehr von John 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
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final TaglessJohn 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
 
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
 
Streams for (Co)Free!
Streams for (Co)Free!Streams for (Co)Free!
Streams for (Co)Free!John De Goes
 
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...John De Goes
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and FutureJohn De Goes
 
All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!John De Goes
 
Getting Started with PureScript
Getting Started with PureScriptGetting Started with PureScript
Getting Started with PureScriptJohn De Goes
 
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual AnalyticsSlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual AnalyticsJohn De Goes
 
The Next Great Functional Programming Language
The Next Great Functional Programming LanguageThe Next Great Functional Programming Language
The Next Great Functional Programming LanguageJohn De Goes
 
The Dark Side of NoSQL
The Dark Side of NoSQLThe Dark Side of NoSQL
The Dark Side of NoSQLJohn De Goes
 

Mehr von John De Goes (20)

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 }
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final Tagless
 
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
 
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
 
Streams for (Co)Free!
Streams for (Co)Free!Streams for (Co)Free!
Streams for (Co)Free!
 
MTL Versus Free
MTL Versus FreeMTL Versus Free
MTL Versus Free
 
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and Future
 
All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!
 
Getting Started with PureScript
Getting Started with PureScriptGetting Started with PureScript
Getting Started with PureScript
 
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual AnalyticsSlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
 
The Next Great Functional Programming Language
The Next Great Functional Programming LanguageThe Next Great Functional Programming Language
The Next Great Functional Programming Language
 
The Dark Side of NoSQL
The Dark Side of NoSQLThe Dark Side of NoSQL
The Dark Side of NoSQL
 

Kürzlich hochgeladen

Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 

Kürzlich hochgeladen (20)

Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 

Blazing Fast, Pure Effects without Monads — LambdaConf 2018

  • 1. 1 Blazing Fast, Pure Effects without Monads LambdaConf 2018 By John A. De Goes — @jdegoes
  • 2. 2 1991 1998 2018 - April Eugenio Moggi John Hughes Flavio Brasil F R O M M O N A D S T O A R R O W S A brief history of effects leading to KleisliIO. KleisliIO 2018 - June Notions of computation and monads Generalizing monads to arrows TraneIO: Arrows & tasks in Scala
  • 3. 3 THE TRINITY OF FP Total Deterministic Free of Side-effects
  • 4. 4 THE TRINITY OF FUNCTIONAL PROGRAMMING Total Deterministic Free of Side-effects f : A => B a ∈ A ⇒ f(a) ∈ B
  • 5. 5 THE TRINITY OF FUNCTIONAL PROGRAMMING Total Deterministic Free of Side-effects def notTotal1(a: Int): String = null def notTotal2(a: Int): String = throw new Error(" ") def notTotal3(a: Int): String = notTotal3(a)
  • 6. 6 THE TRINITY OF FUNCTIONAL PROGRAMMING Total Deterministic Free of Side-effects f : A => B b1 = f(a) ∧ b2 = f(a) ⇒ b1 = b2
  • 7. 7 THE TRINITY OF FUNCTIONAL PROGRAMMING Total Deterministic Free of Side-effects def notDeterministic1(a: Int): String = if (Math.random() > 0.5) "Hello" else "Goodbye" def notDeterministic2(a: Int): String = scala.io.StdIn.readLine() def notDeterministic3(a: Int): String = (System.nanoTime() + a).toString
  • 8. 8 THE TRINITY OF FUNCTIONAL PROGRAMMING Total Deterministic Free of Side-effects f : A => B f’s only computational effect is computing B
  • 9. 9 THE TRINITY OF FUNCTIONAL PROGRAMMING Total Deterministic Free of Side-effects def notEffectFree1(a: Int): String = { println("Hello"); a.toString } def notEffectFree2(a: Int): String = { val _ = scala.io.StdIn.readLine() a.toString } def notEffectFree3(a: Int): String = { Logger.log(a); (a * a).toString }
  • 10. 10 THE RICHES OF PURITY Type Reasoning Equality Reasoning
  • 11. 11 Type Reasoning Equality Reasoning def foo1[A](a: A): A def foo2[A](a: A, f: A => A): A def foo3[A, B](f: (A => A) => B): B THE RICHES OF PURITY
  • 12. 12 Type Reasoning Equality Reasoning def println(line: String): Unit def readLine(): String THE RICHES OF PURITY
  • 13. 13 Type Reasoning Equality Reasoning def f = (x: Int) => x * x val b = f(a) val c = b + b // c = b + b // c = f(a) + f(a) // c = (a * a) + (a * a) // c = 2 * a * a THE RICHES OF PURITY
  • 14. 14 Type Reasoning Equality Reasoning def readLine = scala.io.StdIn.readLine() val a = readLine val b = a + a // b = a + a // b = readLine + readLine // !?!?! readLine + readLine != // { val a = readLine; a + a } THE RICHES OF PURITY
  • 15. 15 MONADIC EFFECTS Effects Into Values Values Into Effects The Cost of Value Effects
  • 16. 16
  • 17. 17 EFFECTS INTO VALUES def println(line: String): Unit println IO[Unit] String def println(line: String): IO[Unit]
  • 18. 18 EFFECTS INTO VALUES IO[A] Immutable value produced by the effect Immutable value describing the effect
  • 19. 19 EFFECTS INTO VALUES sealed trait IO[A] { def map[B](f: A => B): IO[B] = flatMap((a: A) => IO.point(f(a))) def flatMap[B](f: A => IO[B]): IO[B] = FlatMap(this, f) } object IO { def point[A](a: A): IO[A] = Point(a) } final case class PrintLn(line: String) extends IO[Unit] final case class ReadLine() extends IO[String] final case class FlatMap[A, B](fa: IO[A], f: A => IO[B]) extends IO[B] final case class Point[A](a: A) extends IO[A]
  • 20. 20 def readLine(): String def println(line: String): Unit val name = readLine() println("Hello " + name + ", how are you?") EFFECTS INTO VALUES println IO[Unit] def readLine: IO[String] def println(line: String): IO[Unit] val program = for { name <- readLine _ <- println("Hello " + name + ", how are you?") } yield () readLine IO[String] String Unit
  • 21. 21 VALUES INTO EFFECTS def unsafePerformIO(io: IO[A]): A = io match { case PrintLn(line) => println(line) case ReadLine() => readLine() case FlatMap(fa, f) => unsafePerformIO(f(unsafePerformIO(fa))) case Point(a) => a }
  • 22. 22 THE COST OF VALUE EFFECTS println F[Unit] class SS { for { name <- readLine _ <- println("Hello " + name + ", how are you?") } yield () readLine F[String] String Unit
  • 23. 23 THE COST OF VALUE EFFECTS readLine.flatMap(name => printLn("Hello, " + name + ", how are you?")) Allocations Allocation Megamorphic Dispatch
  • 24. 24 THE COST OF VALUE EFFECTS 1 Statement in Procedural Programming 4 Extra Allocations, 1 Extra Megamorphic Dispatch in Functional Programming =
  • 25. 25 IO.sync { App.main() } THE COST OF VALUE EFFECTS Monolith Composed Pure Values
  • 26. 26 THE COST OF VALUE EFFECTS Future
  • 27. 27 KLEISLI EFFECTS Effects Into Values Values Into Effects The Cost of Value Effects
  • 28. 28
  • 29. 29 EFFECTS INTO VALUES def println(line: String): Unit println FunctionIO[String, Unit] val println: FunctionIO[String, Unit]
  • 30. 30 EFFECTS INTO VALUES FunctionIO[A, B] Immutable input value to the function Immutable value describing the effectful function Immutable output value from the function
  • 31. 31 EFFECTS INTO VALUES final case class FunctionIO[A, B](apply0: A => IO[B]) extends (A => IO[B]) { def apply(a: A): IO[B] = apply0(a) def andThen[C](f: FunctionIO[B, C]): FunctionIO[A, C] = FunctionIO(a => apply(a).flatMap(f.apply)) } object FunctionIO { def lift[A, B](f: A => B): FunctionIO[A, B] = FunctionIO(IO.point.compose(f)) }
  • 32. 32 def readLine(): String def println(line: String): Unit val name = readLine() println("Hello " + name + ", how are you?") EFFECTS INTO VALUES val readLine: FunctionIO[Unit, String] val println: FunctionIO[String, Unit] val program = readLine .andThen(lift((name: String) => "Hello, " + name + ", how are you?")) .andThen(println) readLine FunctionIO[Unit, String] <anonymous> FunctionIO[String,String] println FunctionIO[String, Unit]
  • 33. 33 VALUES INTO EFFECTS val program: FunctionIO[Unit, Unit] unsafePerformIO(program())
  • 34. 34 THE COST OF EFFECT VALUES readLine.andThen(lift((name: String) => "Hello, " + name + ", how are you?")) .andThen(println) readLine FunctionIO[Unit, String] <anonymous> FunctionIO[String,String] println FunctionIO[String, Unit]
  • 35. 35 Megamorphic Dispatches final case class FunctionIO[A, B](apply: A => IO[B]) THE COST OF EFFECT VALUES readLine.andThen(println) Allocations Allocations
  • 36. 36 THE COST OF EFFECT VALUES 1 Statement in Procedural Programming 6 Extra Allocations, 3 Extra Megamorphic Dispatches in Functional Programming =
  • 37. 37 THE PROMISE OF KLEISLIIO sealed trait FunctionIO[A, B] extends (A => IO[B]) { ... } final class Pure[A, B](val apply0: A => IO[B]) extends FunctionIO[A, B] { def apply(a: A): IO[B] = apply0(a) } final class Impure[A, B](val apply0: A => B) extends FunctionIO[A, B] { def apply(a: A): IO[B] = IO.point(apply0(a)) } val readLine: FunctionIO[Unit, String] = new Impure(_ => scala.io.StdIn.readLine()) val printLn: FunctionIO[String, Unit] = new Impure(println)
  • 38. 38 THE PROMISE OF KLEISLIIO class Impure[A, B](val apply0: A => B) 1 Invocation in Procedural Programming 0 Extra Allocations, 1 Extra Dispatch in Functional Programming =
  • 39. 39 KLEISLIIO Running KleisliIO Constructing KleisliIO Composing KleisliIO Introducing KleisliIO Optimizing KleisliIO Testing KleisliIO
  • 40. 40 KLEISLIIO sealed trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... } object KleisliIO { class KleisliIOError[E](error: E) extends Throwable { def unsafeCoerce[E2] = error.asInstanceOf[E2] } class Pure[E, A, B](apply0: A => IO[E, B]) extends KleisliIO[E, A, B] { override final def apply(a: A): IO[E, B] = apply0(a) } class Impure[E, A, B](val apply0: A => B) extends KleisliIO[E, A, B] { override final def apply(a: A): IO[E, B] = IO.suspend { try IO.now[E, B](apply0(a)) catch { case e: KleisliIOError[_] => IO.fail[E, B](e.unsafeCoerce[E]) } } } ... }
  • 41. 41 RUNNING KLEISLIIO val printLn: KleisliIO[IOException, String, Unit] printLn("Hello, world!") // IO[IOException, Unit]
  • 42. 42 CONSTRUCTING PURE KLEISLIIO object KleisliIO { ... def pure[E, A, B](f: A => IO[E, B]): KleisliIO[E, A, B] = ??? ... } val printLn: KleisliIO[Void, String, Unit] = KleisliIO.pure((a: String) => IO.sync(println(a)))
  • 43. 43 CONSTRUCTING IMPURE KLEISLIIO object KleisliIO { ... def impure[E, A, B](catcher: PartialFunction[Throwable, E])(f: A => B) ... } val IOExceptions: PartialFunction[Throwable, IOException] = { case io : IOException => io } val printLn: KleisliIO[Void, String, Unit] = KleisliIO.impure(IOExceptions)(println)
  • 44. 44 CONSTRUCTING IMPURE KLEISLIIO object KleisliIO { ... def impureVoid[A, B](f: A => B): KleisliIO[Void, A, B] = ??? ... } val printLn: KleisliIO[Void, String, Unit] = KleisliIO.impureVoid(println)
  • 45. 45 CONSTRUCTING KLEISLIIO object KleisliIO { ... def identity[E, A]: KleisliIO[E, A, A] = ??? ... } A A KleisliIO.identity[Void, Int](1) // IO.point(1)
  • 46. 46 COMPOSING KLEISLIIO trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... def >>>[C](that: KleisliIO[E, B, C]): KleisliIO[E, A, C] = ??? ... } ... A B C A C readLine >>> printLn
  • 47. 47 COMPOSING KLEISLIIO A B C (B, C) => D A D trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... def zipWith[C, D](that: KleisliIO[E, A, C])(f: (B, C) => D): KleisliIO[E, A, D] = ??? ... } readLine.zipWith(readLine)((l1, l2) => l1 + l2)
  • 48. 48 COMPOSING KLEISLIIO trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... def &&&[C]( that: KleisliIO[E, A, C]): KleisliIO[E, A, (B, C)] = ??? ... } A B C A (B,C) readLine &&& readLine
  • 49. 49 COMPOSING KLEISLIIO trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... def |||[C](that: KleisliIO[E, C, B]): KleisliIO[E, Either[A, C], B] ... } A B C Either[A, C] D (fancyPrintLn ||| standardPrintLn)(Left("Fancied!"))
  • 50. 50 COMPOSING KLEISLIIO trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... def first: KleisliIO[E, A, (B, A)] = this &&& KleisliIO.identity[E, A] ... } A B A (B, A) readLine >>> printLn.first // (Unit, String)
  • 51. 51 COMPOSING KLEISLIIO trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... def second: KleisliIO[E, A, (A, B)] = KleisliIO.identity[E, A] &&& this ... } A B A (A, B) readLine >>> printLn.second // (String, Unit)
  • 52. 52 COMPOSING KLEISLIIO trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... def left[C]: KleisliIO[E, Either[A, C], Either[B, C]] = ??? ... } Either[A, C] Either[B, C] A B printLn.left[String]( Left("Hello")) // Left[Unit]
  • 53. 53 COMPOSING KLEISLIIO trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... def right[C]: KleisliIO[E, Either[A, C], Either[B, C]] = ??? ... } Either[A, C] Either[B, C] A B printLn.right[String]( Right("Hello")) // Right[Unit]
  • 54. 54 COMPOSING KLEISLIIO trait KleisliIO[E, A, B] extends (A => IO[E, B]) { ... def asEffect: KleisliIO[E, A, A] = self.first >>> KleisliIO._2 ... } A A B printLn.asEffect // String
  • 55. 55 COMPOSING KLEISLIIO object KleisliIO { ... def test[E, A](cond: KleisliIO[E, A, Boolean]): KleisliIO[E, A, Either[A, A]] = ??? ... } test(KleisliIO.lift(_ > 2))(4) // IO[Void, Either[Int, Int]] cond A Bool A Either[A, A] Right(a)Left(a)
  • 56. 56 COMPOSING KLEISLIIO object KleisliIO { ... def ifThenElse[E, A, B](cond : KleisliIO[E, A, Boolean]) (then0: KleisliIO[E, A, B])(else0: KleisliIO[E, A, B]): KleisliIO[E, A, B] = test[E, A](cond) >>> (then0 ||| else0) ... } ifThenElse(KleisliIO.lift(_ == "John"))(printLn)(const(())) A B else0 then0 A BA B cond A Bool
  • 57. 57 COMPOSING KLEISLIIO object KleisliIO { ... def whileDo[E, A](check: KleisliIO[E, A, Boolean]) (body : KleisliIO[E, A, A]): KleisliIO[E, A, A] = ??? ... } A A A Boolean A Abody check readLine >>> whileDo(lift(_ != “John”)) { KleisliIO.point(“Wrong name”) >>> printLn >>> readLine }
  • 58. 58 OPTIMIZING KLEISLIIO final def compose[E, A, B, C](second: KleisliIO[E, B, C], first: KleisliIO[E, A, B]): KleisliIO[E, A, C] = (second, first) match { case (second: Impure[_, _, _], first: Impure[_, _, _]) => new Impure(second.apply0.compose(first.apply0)) case _ => new Pure((a: A) => first(a).flatMap(second)) }
  • 59. 59 OPTIMIZING KLEISLIIO final def ifThenElse[E, A, B](cond: KleisliIO[E, A, Boolean]) (then0: KleisliIO[E, A, B])(else0: KleisliIO[E, A, B]): KleisliIO[E, A, B] = (cond, then0, else0) match { case (cond: Impure[_, _, _], then0: Impure[_, _, _], else0: Impure[_, _, _]) => new Impure[E, A, B](a => if (cond.apply0(a)) then0.apply0(a) else else0.apply0(a)) case _ => test[E, A](cond) >>> (then0 ||| else0) }
  • 60. 60 OPTIMIZING KLEISLIIO final def whileDo[E, A](check: KleisliIO[E, A, Boolean])(body: KleisliIO[E, A, A]): KleisliIO[E, A, A] = (check, body) match { case (check: Impure[_, _, _], body: Impure[_, _, _]) => new Impure[E, A, A]({ (a0: A) => val cond = check.apply0 val update = body.apply0 var a = a0 while (cond(a)) { a = update(a) } a }) case _ => lazy val loop: KleisliIO[E, A, A] = KleisliIO.pure((a: A) => check(a).flatMap((b: Boolean) => if (b) body(a).flatMap(loop) else IO.now(a))) loop }
  • 61. 61 TESTING KLEISLIIO - ARRAY FILL Output: An array filled with 10,000 elements in increasing order.
  • 62. 62 TESTING KLEISLIIO - ARRAY FILL def arrayFill(array: Array[Int]): KleisliIO[Void, Int] = { val condition = KleisliIO.lift(i => i < array.length) val update = KleisliIO.impureVoid{ i => array.update(i, i); i + 1 } KleisliIO.whileDo(condition)(update) } def arrayFill(array: Array[Int])(i: Int): IO[Unit] = if (i >= array.length) IO.unit else IO(array.update(i, i)).flatMap(_ => arrayFill(array)(i + 1)) KleisliIO Array Fill Monadic Array Fill
  • 63. 63 TESTING KLEISLIIO - ARRAY FILL 7958.946 ops/s 3622.744 ops/s 3689.406 ops/s Array Fill 2.18x Faster!
  • 64. 64 TESTING KLEISLIIO - BUBBLE SORT Input: Array of 10000 element with reversed order Output: bubbleSort(array) bubbleSort(array): i <- 1 to 10000 j <- i + 1 to 9999 lessThanEqual = array(i) <= array(j) if (!lessThanEqual) swap(array, i, j)
  • 65. 65 TESTING KLEISLIIO - BUBBLE SORT val sort: KleisliIO[Void, Int, Unit] = KleisliIO .whileDo(outerLoopCheck)( innerLoopStart >>> KleisliIO.whileDo(innerLoopCheck)( extractIJIndexValue >>> KleisliIO.ifNotThen(lessThanEqual)(swapIJ) >>> extractIJAndIncrementJ ) >>> extractIAndIncrementI ) sort(0) def outerLoop(i: Int): IO[Unit] = if (i >= array.length - 1) IO.unit else innerLoop(i, i + 1).flatMap(_ => outerLoop(i + 1)) def innerLoop(i: Int, j: Int): IO[Unit] = if (j >= array.length) IO.unit else IO((array(i), array(j))).flatMap { case (ia, ja) => val maybeSwap = if (lessThanEqual0(ia, ja)) IO.unit else swapIJ(i, ia, j, ja) maybeSwap.flatMap(_ => innerLoop(i, j + 1)) } outerLoop(0) KleisliIO Bubble sort Monadic Bubble sort
  • 66. 66 TESTING KLEISLIIO - BUBBLE SORT 58.811 ops/s 41.545 ops/s 33.229 ops/s 1.57x Faster! Bubble Sort
  • 67. 67 W H E R E F R O M H E R E A brief roadmap for KleisliIO. ? Infinite Composition Recursion Combinator Low-Cost Propagation
  • 68. 68 THANK YOU! Thanks to the staff, volunteers, and speakers of LambdaConf, and to Wiem Zine El Abidine for help with the development and implementation of KleisliIO. Follow me @jdegoes Follow Wiem @wiemzin Join Scalaz at gitter.im/scalaz/scalaz