Skip to main content

CanCatch

CanCatch#

CanCatch lets you catch NonFatal Throwable in the F[A] and turned it into F[Either[Throwable, A]]. It takes a function from Throwable to your own error type, yet it can handle only NonFatal ones as already mentioned.

trait CanCatch[F[_]] {  def catchNonFatal[A, B](fb: => F[B])(f: Throwable => A): F[A \/ B]
  def catchNonFatalEither[A, B](fab: => F[A \/ B])(f: Throwable => A): F[A \/ B]
  def catchNonFatalEitherT[A, B](fab: => EitherT[F, A, B])(f: Throwable => A): EitherT[F, A, B]}

CanCatch.catchNonFatal#

CanCatch[F].catchNonFatal[A, B] lets you catch NonFatal Throwable from F[B] and returns F[A \/ B].

How to Use#

import scalaz.effect._
import effectie.scalaz._
val fa = CanCatch[IO].catchNonFatal(    IO(throw new RuntimeException("Something's wrong!"))  )(identity)// fa: IO[scalaz.\/[Throwable, Nothing]] = scalaz.effect.IO$$anon$7@66e85b15
fa.unsafePerformIO()// res1: scalaz.\/[Throwable, Nothing] = -\/(//   a = java.lang.RuntimeException: Something's wrong!// )

Happy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)}
def doSomethingBad(n: Int): Int =  if (n < 0)    throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")  else    n * 2
def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  CanCatch[F].catchNonFatal(    for {      a <- pureOf(n + 100)      b <- effectOf(doSomethingBad(a))    } yield b  )(MyError.nonFatalThrowable)
val fa = doSomething[IO](1)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@13a4ef1dval result = fa.unsafePerformIO()// result: MyError \/ Int = \/-(b = 202)result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(MyError.NonFatalThrowable(a)) =>    println(s"Result: Failed with $a")}// Result is 202

Unhappy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)}
def doSomethingBad(n: Int): Int =if (n < 0)  throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")else  n * 2

def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  CanCatch[F].catchNonFatal(    for {      a <- pureOf(n + 100)      b <- effectOf(doSomethingBad(a))    } yield b  )(MyError.nonFatalThrowable)
val fa = doSomething[IO](-101)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@42ba88f5val result = fa.unsafePerformIO()// result: MyError \/ Int = -\/(//   a = NonFatalThrowable(//     throwable = java.lang.IllegalArgumentException: n cannot be a negative number. [n: -1]//   )// )result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(MyError.NonFatalThrowable(a)) =>    println(s"Result: Failed with $a")}// Result: Failed with java.lang.IllegalArgumentException: n cannot be a negative number. [n: -1]

CanCatch.catchNonFatalEither#

CanCatch[F].catchNonFatalEither[A, B] lets you catch NonFatal Throwable from F[A \/ B] and returns F[A \/ B].

How to Use#

import scalaz._import scalaz.effect._
import effectie.scalaz._
val fa = CanCatch[IO].catchNonFatalEither(    IO((throw new RuntimeException("Something's wrong!")): Throwable \/ Int)  )(identity)// fa: IO[Throwable \/ Int] = scalaz.effect.IO$$anon$7@1af793d4
fa.unsafePerformIO()// res19: Throwable \/ Int = -\/(//   a = java.lang.RuntimeException: Something's wrong!// )

Happy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  case object DivideByZero extends MyError    def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)
  def divideByZero: MyError = DivideByZero}
def divide100By(n: Int): MyError \/ Int =  if (n === 0)    MyError.divideByZero.left[Int]  else    (100 / n).right[MyError]
def doSomethingBad(n: Int): Int =  if (n < 0)    throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")  else    n * 2
def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  CanCatch[F].catchNonFatalEither(    for {      aOrB <- pureOf(divide100By(n))      c <- effectOf(aOrB.map(b => doSomethingBad(b)))    } yield c  )(MyError.nonFatalThrowable)
val fa = doSomething[IO](1)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@3f9e07dval result = fa.unsafePerformIO()// result: MyError \/ Int = \/-(b = 200)result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(a) =>    println(s"Result: Failed with $a")}// Result is 200

Unhappy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  case object DivideByZero extends MyError    def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)
  def divideByZero: MyError = DivideByZero}
def divide100By(n: Int): MyError \/ Int =  if (n === 0)    MyError.divideByZero.left[Int]  else    (100 / n).right[MyError]
def doSomethingBad(n: Int): Int =if (n < 0)  throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")else  n * 2
def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  CanCatch[F].catchNonFatalEither(    for {      aOrB <- pureOf(divide100By(n))      c <- effectOf(aOrB.map(b => doSomethingBad(b)))    } yield c  )(MyError.nonFatalThrowable)
val fa = doSomething[IO](-1)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@1a5a1542val result = fa.unsafePerformIO()// result: MyError \/ Int = -\/(//   a = NonFatalThrowable(//     throwable = java.lang.IllegalArgumentException: n cannot be a negative number. [n: -100]//   )// )result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(a) =>    println(s"Result: Failed with $a")}// Result: Failed with NonFatalThrowable(java.lang.IllegalArgumentException: n cannot be a negative number. [n: -100])

CanCatch.catchNonFatalEitherT#

CanCatch[F].catchNonFatalEitherT[A, B] lets you catch NonFatal Throwable from EitherT[F, A, B] and returns EitherT[F, A, B].

How to Use#

import scalaz._import scalaz.effect._
import effectie.scalaz._
val fa = CanCatch[IO].catchNonFatalEitherT(    EitherT(IO((throw new RuntimeException("Something's wrong!")): Throwable \/ Int))  )(identity)// fa: EitherT[IO, Throwable, Int] = EitherT(//   run = scalaz.effect.IO$$anon$7@5ce3adb7// )
fa.run.unsafePerformIO()// res37: Throwable \/ Int = -\/(//   a = java.lang.RuntimeException: Something's wrong!// )

Happy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._import effectie.scalaz.EitherTSupport._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  case object DivideByZero extends MyError    def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)
  def divideByZero: MyError = DivideByZero}
def divide100By(n: Int): MyError \/ Int =  if (n === 0)    MyError.divideByZero.left[Int]  else    (100 / n).right[MyError]
def doSomethingBad(n: Int): Int =  if (n < 0)    throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")  else    n * 2
def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  CanCatch[F].catchNonFatalEitherT(    for {      b <- EitherT(pureOf(divide100By(n)))      c <- eitherTRight[MyError](doSomethingBad(b))    } yield c  )(MyError.nonFatalThrowable).run
val fa = doSomething[IO](1)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@1e406293val result = fa.unsafePerformIO()// result: MyError \/ Int = \/-(b = 200)result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(a) =>    println(s"Result: Failed with $a")}// Result is 200

Unhappy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.EitherTSupport._import effectie.scalaz.Effectful._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  case object DivideByZero extends MyError    def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)
  def divideByZero: MyError = DivideByZero}
def divide100By(n: Int): MyError \/ Int =  if (n === 0)    MyError.divideByZero.left[Int]  else    (100 / n).right[MyError]
def doSomethingBad(n: Int): Int =if (n < 0)  throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")else  n * 2
def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  CanCatch[F].catchNonFatalEitherT(    for {      b <- EitherT(pureOf(divide100By(n)))      c <- eitherTRight[MyError](doSomethingBad(b))    } yield c  )(MyError.nonFatalThrowable).run
val fa = doSomething[IO](-1)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@3a0556bbval result = fa.unsafePerformIO()// result: MyError \/ Int = -\/(//   a = NonFatalThrowable(//     throwable = java.lang.IllegalArgumentException: n cannot be a negative number. [n: -100]//   )// )result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(a) =>    println(s"Result: Failed with $a")}// Result: Failed with NonFatalThrowable(java.lang.IllegalArgumentException: n cannot be a negative number. [n: -100])

Catching#

Catching.catchNonFatal provides a convenient way to use CanCatch to catch NonFatal Throwable in the F[A] and turned it into F[Either[Throwable, A]]. Just like CanCatch, it takes a function from Throwable to your own error type, yet it can handle only NonFatal ones as already mentioned.

Catching.catchNonFatal#

catchNonFatal lets you catch NonFatal Throwable from F[B] and returns F[A \/ B].

How to Use#

import scalaz.effect._
import effectie.scalaz.Catching._
val fa = catchNonFatal(    IO((throw new RuntimeException("Something's wrong!")): Int)  )(identity)// fa: IO[scalaz.\/[Throwable, Int]] = scalaz.effect.IO$$anon$7@3d2b1004
fa.unsafePerformIO()// res55: scalaz.\/[Throwable, Int] = -\/(//   a = java.lang.RuntimeException: Something's wrong!// )

Happy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._import effectie.scalaz.Catching._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)}
def doSomethingBad(n: Int): Int =  if (n < 0)    throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")  else    n * 2
def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  catchNonFatal(    for {      a <- pureOf(n + 100)      b <- effectOf(doSomethingBad(a))    } yield b  )(MyError.nonFatalThrowable)
val fa = doSomething[IO](1)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@1da76142val result = fa.unsafePerformIO()// result: MyError \/ Int = \/-(b = 202)result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(MyError.NonFatalThrowable(a)) =>    println(s"Result: Failed with $a")}// Result is 202

Unhappy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._import effectie.scalaz.Catching._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)}
def doSomethingBad(n: Int): Int =if (n < 0)  throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")else  n * 2

def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  catchNonFatal(    for {      a <- pureOf(n + 100)      b <- effectOf(doSomethingBad(a))    } yield b  )(MyError.nonFatalThrowable)
val fa = doSomething[IO](-101)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@42c4fb51val result = fa.unsafePerformIO()// result: MyError \/ Int = -\/(//   a = NonFatalThrowable(//     throwable = java.lang.IllegalArgumentException: n cannot be a negative number. [n: -1]//   )// )result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(MyError.NonFatalThrowable(a)) =>    println(s"Result: Failed with $a")}// Result: Failed with java.lang.IllegalArgumentException: n cannot be a negative number. [n: -1]

Catching.catchNonFatalEither#

Catching.catchNonFatalEither provides a convenient way to use CanCatch to catch NonFatal Throwable from F[A \/ B] and returns F[A \/ B].

How to Use#

import scalaz._import scalaz.effect._
import effectie.scalaz.Catching._
val fa = catchNonFatalEither(    IO((throw new RuntimeException("Something's wrong!")): Throwable \/ Int)  )(identity)// fa: IO[Throwable \/ Int] = scalaz.effect.IO$$anon$7@3b70366
fa.unsafePerformIO()// res73: Throwable \/ Int = -\/(//   a = java.lang.RuntimeException: Something's wrong!// )

Happy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._import effectie.scalaz.Catching._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  case object DivideByZero extends MyError    def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)
  def divideByZero: MyError = DivideByZero}
def divide100By(n: Int): MyError \/ Int =  if (n === 0)    MyError.divideByZero.left[Int]  else    (100 / n).right[MyError]
def doSomethingBad(n: Int): Int =  if (n < 0)    throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")  else    n * 2
def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  catchNonFatalEither(    for {      aOrB <- pureOf(divide100By(n))      c <- effectOf(aOrB.map(b => doSomethingBad(b)))    } yield c  )(MyError.nonFatalThrowable)
val fa = doSomething[IO](1)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@139c6ddeval result = fa.unsafePerformIO()// result: MyError \/ Int = \/-(b = 200)result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(a) =>    println(s"Result: Failed with $a")}// Result is 200

Unhappy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._import effectie.scalaz.Catching._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  case object DivideByZero extends MyError    def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)
  def divideByZero: MyError = DivideByZero}
def divide100By(n: Int): MyError \/ Int =  if (n === 0)    MyError.divideByZero.left[Int]  else    (100 / n).right[MyError]
def doSomethingBad(n: Int): Int =if (n < 0)  throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")else  n * 2
def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  catchNonFatalEither(    for {      aOrB <- pureOf(divide100By(n))      c <- effectOf(aOrB.map(b => doSomethingBad(b)))    } yield c  )(MyError.nonFatalThrowable)
val fa = doSomething[IO](-1)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@f41a911val result = fa.unsafePerformIO()// result: MyError \/ Int = -\/(//   a = NonFatalThrowable(//     throwable = java.lang.IllegalArgumentException: n cannot be a negative number. [n: -100]//   )// )result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(a) =>    println(s"Result: Failed with $a")}// Result: Failed with NonFatalThrowable(java.lang.IllegalArgumentException: n cannot be a negative number. [n: -100])

Catching.catchNonFatalEitherT#

Catching.catchNonFatalEitherT provides a convenient way to use CanCatch to catch NonFatal Throwable from EitherT[F, A, B] and returns EitherT[F, A, B].

How to Use#

import scalaz._import scalaz.effect._
import effectie.scalaz.Catching._
val fa = catchNonFatalEitherT[IO](    EitherT(IO((throw new RuntimeException("Something's wrong!")): Throwable \/ Int))  )(identity)// fa: EitherT[IO, Throwable, Int] = EitherT(//   run = scalaz.effect.IO$$anon$7@6c3d4cd5// )
fa.run.unsafePerformIO()// res91: Throwable \/ Int = -\/(//   a = java.lang.RuntimeException: Something's wrong!// )

Happy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._import effectie.scalaz.Catching._import effectie.scalaz.EitherTSupport._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  case object DivideByZero extends MyError    def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)
  def divideByZero: MyError = DivideByZero}
def divide100By(n: Int): MyError \/ Int =  if (n === 0)    MyError.divideByZero.left[Int]  else    (100 / n).right[MyError]
def doSomethingBad(n: Int): Int =  if (n < 0)    throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")  else    n * 2
def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  catchNonFatalEitherT(    for {      b <- EitherT(pureOf(divide100By(n)))      c <- eitherTRight[MyError](doSomethingBad(b))    } yield c  )(MyError.nonFatalThrowable).run
val fa = doSomething[IO](1)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@3ea3dbbaval result = fa.unsafePerformIO()// result: MyError \/ Int = \/-(b = 200)result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(a) =>    println(s"Result: Failed with $a")}// Result is 200

Unhappy Path Example#

import scalaz._import Scalaz._import scalaz.effect._
import effectie.scalaz._import effectie.scalaz.Effectful._import effectie.scalaz.Catching._import effectie.scalaz.EitherTSupport._
sealed trait MyErrorobject MyError {  final case class NonFatalThrowable(throwable: Throwable) extends MyError  case object DivideByZero extends MyError    def nonFatalThrowable(throwable: Throwable): MyError    = NonFatalThrowable(throwable)
  def divideByZero: MyError = DivideByZero}
def divide100By(n: Int): MyError \/ Int =  if (n === 0)    MyError.divideByZero.left[Int]  else    (100 / n).right[MyError]
def doSomethingBad(n: Int): Int =if (n < 0)  throw new IllegalArgumentException(s"n cannot be a negative number. [n: $n]")else  n * 2
def doSomething[F[_]: Fx: CanCatch: Monad](  n: Int): F[MyError \/ Int] =  catchNonFatalEitherT(    for {      b <- EitherT(pureOf(divide100By(n)))      c <- eitherTRight[MyError](doSomethingBad(b))    } yield c  )(MyError.nonFatalThrowable).run
val fa = doSomething[IO](-1)// fa: IO[MyError \/ Int] = scalaz.effect.IO$$anon$7@2cb68465val result = fa.unsafePerformIO()// result: MyError \/ Int = -\/(//   a = NonFatalThrowable(//     throwable = java.lang.IllegalArgumentException: n cannot be a negative number. [n: -100]//   )// )result match {  case \/-(b) =>    println(s"Result is $b")  case -\/(a) =>    println(s"Result: Failed with $a")}// Result: Failed with NonFatalThrowable(java.lang.IllegalArgumentException: n cannot be a negative number. [n: -100])