Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
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)(_ :: _))
}