Skip to main content
Version: v1

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@3fc3b107

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 MyError
object 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@3fc8fbf1
val 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 MyError
object 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@1da13e86
val 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@118591af

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 MyError
object 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@398a3847
val 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 MyError
object 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@43fce30
val 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@712c20ff
// )

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 MyError
object 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@15b6d547
val 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 MyError
object 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@50d24d6
val 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@16bf45cd

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 MyError
object 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@207a495c
val 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 MyError
object 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@4c87f1b3
val 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@33646feb

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 MyError
object 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@113debde
val 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 MyError
object 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@136d525
val 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@21ed79ed
// )

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 MyError
object 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@2e786ab6
val 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 MyError
object 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@64905c85
val 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])