Skip to content

Instantly share code, notes, and snippets.

@rbobillot
Created January 13, 2020 16:23
Show Gist options
  • Save rbobillot/cd02ef313549aeea6893941ca03fef9b to your computer and use it in GitHub Desktop.
Save rbobillot/cd02ef313549aeea6893941ca03fef9b to your computer and use it in GitHub Desktop.
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