Skip to content
{{ message }}

Instantly share code, notes, and snippets.

# jonnylaw/ErrorHandling.scala

Created Jan 5, 2017
 import cats.implicits._ import cats.data.OptionT object ErrorHandling { // Calculate the square root of a positive number or return an exception (which isn't obvious from the return type) def unsafe_sqrt(a: Double): Double = { if (a > 0) math.sqrt(a) else throw new Exception("Can't calculate square root of negative number") } // Calculate the square root of a positive number and return either a Success containing the result // or a Failure containing an exception (if the number supplied is negative) // This makes it clear to users that this function can fail def try_sqrt(a: Double): Try[Double] = { if (a > 0) Success(math.sqrt(a)) else Failure(throw new Exception("Can't calculate square root of negative number")) } // Calculate the square root of a positive number and return an optional value def option_sqrt(a: Double): Option[Double] = { if (a > 0) Some(math.sqrt(a)) else None } // In order to chain operations we can use compose on the function unsafe_sqrt // this is because the function has compatible types (Double => Double) def sqrt_twice = unsafe_sqrt _ compose unsafe_sqrt _ // In order to chain the option_sqrt function, we need to invoke flatMap, since the // types are not compatible def sqrt_twice_option(x: Double): Option[Double] = option_sqrt(x) flatMap option_sqrt // A naive attempt to compose a try and an option using nested type constructors // This appears to work, but becomes more difficult if we want to work with the return type def sqrt_twice_2(a: Double): Try[Option[Double]] = try_sqrt(a) map option_sqrt // Another function we want to apply to the result of sqrt_twice_2 def f(a: Double) = a + 1 // Function which applies f to the result of sqrt_twice_2 def apply_f = sqrt_twice_2(81) map (_.map(f)) // We can remove the extra map function by utilising OptionT from cats (http://typelevel.org/cats/), // a monad transformer for Option def sqrt_twice_trans(a: Double): OptionT[Try, Double] = OptionT.fromOption[Try](option_sqrt(a)) flatMap (b => OptionT.liftF(try_sqrt(b)) def apply_f_trans = sqrt_twice_trans(81) map f }
to join this conversation on GitHub. Already have an account? Sign in to comment