Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
81 lines (66 sloc) 2.43 KB
package fpinscala.errorhandling
// hide std library `Option`, `Some` and `Either`, since we are writing our
// own in this chapter
import scala.{Option => _, Some => _, Either => _, _}
sealed trait Option[+A] {
def map[B](f: A => B): Option[B] = this match {
case None => None
case Some(x) => Some(f(x))
}
def getOrElse[B>:A](default: => B): B = this match {
case None => default
case Some(x) => x
}
def flatMap[B](f: A => Option[B]): Option[B] = map(f) getOrElse None
def orElse[B>:A](ob: => Option[B]): Option[B] =
this map (Some(_)) getOrElse ob
def filter(f: A => Boolean): Option[A] = this match {
case Some(x) if f(x) => this
case _ => None
}
}
case class Some[+A](get: A) extends Option[A]
case object None extends Option[Nothing]
object Option {
def failingFn(i: Int): Int = {
// `val y: Int = ...` declares `y` as having type `Int`, and sets it
// equal to the right hand side of the `=`.
val y: Int = throw new Exception("fail!")
try {
val x = 42 + 5
x + y
}
// A `catch` block is just a pattern matching block like the ones
// we've seen. `case e: Exception` is a pattern that matches any
// `Exception`, and it binds this value to the identifier `e`. The
// match returns the value 43.
catch { case e: Exception => 43 }
}
def failingFn2(i: Int): Int = {
try {
val x = 42 + 5
// A thrown Exception can be given any type; here we're annotating
// it with the type `Int`
x + ((throw new Exception("fail!")): Int)
}
catch { case e: Exception => 43 }
}
def mean(xs: Seq[Double]): Option[Double] =
if (xs.isEmpty) None
else Some(xs.sum / xs.length)
def variance(xs: Seq[Double]): Option[Double] =
mean(xs) flatMap (m => mean(xs.map(x => math.pow(x - m, 2))))
// def map2[A,B,C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] =
// (a, b) match {
// case (_, None) => None
// case (None, _) => None
// case (Some(x), Some(y)) => Some(f(x, y))
// }
// Exercise 4.3 -- using hint
def map2[A,B,C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] =
a flatMap (a1 => b map (b1 => f(a1, b1)))
def sequence[A](a: List[Option[A]]): Option[List[A]] =
a.foldRight[Option[List[A]]](Some(Nil))((h, t) => map2(h, t)(_ :: _))
def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] =
a.foldRight[Option[List[B]]](Some(Nil))((h, t) => map2(f(h), t)(_ :: _))
}