Scala 関数型デザイン&プログラミング 4章 Exercise
Excercise 4.8はあまり自信がない。
// 4.1 def map[B](f: A => B): Option[B] = this match { case None => None case Some(x) => Some(f(x)) } def flatMap[B](f: A => Option[B]): Option[B] = this.map(f).getOrElse(None) def getOrElse[B >: A](default: => B): B = this match { case None => default case Some(x) => x } def orElse[B >: A](ob: => Option[B]): Option[B] = this.map(x => Some(x)).getOrElse(ob) def filter(f: A => Boolean): Option[A] = this.flatMap { x => if (f(x)) Some(x) else None } // 4.2 def variance(xs: Seq[Double]): Option[Double] = { mean(xs).map { m => xs.map { x => Math.pow(x - m, 2) } }.flatMap(mean) } // 4.3 def map2[A, B, C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] = a.flatMap { aa => b.map { bb => f(aa, bb) } } // 4.4 def sequence[A](a: List[Option[A]]): Option[List[A]] = a.foldRight(Some(Nil): Option[List[A]]) { (x, acc) => map2(x, acc)(_ :: _) } // 4.5 def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] = a.foldRight(Some(Nil): Option[List[B]]) { (x, acc) => map2(f(x), acc)(_ :: _) } // 4.6 def map[B](f: A => B): Either[E, B] = this match { case Left(e) => Left(e) case Right(a) => Right(f(a)) } def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B] = this match { case Left(e) => Left(e) case Right(a) => f(a) } def orElse[EE >: E, B >: A](b: => Either[EE, B]): Either[EE, B] = this match { case Left(_) => b case Right(a) => Right(a) } def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] = this.flatMap { aa => b.map { bb => f(aa, bb) } } // 4.7 def sequence[E, A](es: List[Either[E, A]]): Either[E, List[A]] = es.foldRight(Right(Nil): Either[E, List[A]]) { (x, a) => x.map2(a)(_ :: _) } def traverse[E, A, B](as: List[A])(f: A => Either[E, B]): Either[E, List[B]] = as.foldRight(Right(Nil): Either[E, List[B]]) { (x, a) => f(x).map2(a)(_ :: _) } // 4.8 // Either[List[E], A]を使用するようにmkPerson、map2を変更する。