Created
January 13, 2020 16:23
-
-
Save rbobillot/cd02ef313549aeea6893941ca03fef9b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cats.effect.IO | |
object Impure { | |
def pureAddIntPair(x: Int, y: Int): Int = x + y | |
// Possible side effect: NumberFormatException | |
// => No Referential Transparency | |
def impureParseInt(s: String): Int = Integer.parseInt(s) | |
// Multiple side effects: | |
// - NumberFormatException can be thrown | |
// - IOException can be thrown | |
def impureAddAndPrint(s1: String, s2: String): Int = { | |
val x = impureParseInt(s1) + impureParseInt(s2) // possible failure | |
println(x) // possible failure | |
x | |
} | |
impureAddAndPrint("40", "2") // possible failure | |
} | |
object Purer { | |
def pureAddIntPair(x: Int, y: Int): Int = x + y | |
// IO.apply is lazy, Integer.parseInt won't be computed | |
// until the whole program is ran | |
def pureParseInt(s: String): IO[Int] = IO.apply(Integer parseInt s) | |
// No side effect, an IO Monad is ALWAYS returned, no matter what | |
def pureAddAndPrint(s1: String, s2: String): IO[Int] = | |
for { | |
x <- pureParseInt(s1) | |
y <- pureParseInt(s2) | |
z <- IO.pure(x + y) | |
_ <- IO.apply(println(z)) | |
} yield z | |
pureAddAndPrint("40", "2").unsafeRunSync() // possible failure | |
} | |
object Pure { | |
sealed trait BizException | |
case class BizIOException(ex: Throwable) extends BizException | |
case class BizNbException(ex: Throwable) extends BizException | |
def attemptWith[L <: BizException, R](e: Throwable => L)(sfx: => R): IO[Either[L, R]] = | |
IO.apply(sfx).attempt.map(_.left.map(e)) | |
def pureAddIntPair(x: Int, y: Int): Int = x + y // nothing changes here | |
def pureAddBizIntPair[L <: BizException](x: Either[L, Int], y: Either[L, Int]) = | |
for (i <- x; j <- y) yield pureAddIntPair(i, j) | |
def pureParseBizInt(s: String) = | |
attemptWith(BizNbException)(Integer parseInt s) | |
def purePrint[T](t: T) = | |
attemptWith(BizIOException)(println(t)) | |
def pureAddAndPrint(s1: String, s2: String): IO[Either[BizException, Int]] = | |
for { | |
x <- pureParseBizInt(s1) | |
y <- pureParseBizInt(s2) | |
z <- IO.pure(pureAddBizIntPair(x, y)) | |
_ <- purePrint(z) | |
} yield z | |
pureAddAndPrint("40", "2").map { | |
case Left(nb: BizNbException) => // handle number format error | |
case Left(io: BizIOException) => // handle io error | |
case Right(n: Int) => // handle success | |
}.unsafeRunSync() // no more failure | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment