不是用异常来处理错误(2)

Option不会告诉我们在异常条件下发生了什么错误,它只是给我们一个None,表示没有可用的值。但是有时候我们想知道更多,比如想要一个字符串给出更多的信息或者异常发生时想知道实际错误是什么。这时候我们需要Either数据类型。
Either数据类型

sealed trait Either[+E, +A] {

}

case class Left[+E](e: E) extends Either[E, Nothing]

case class Right[+A](a: A) extends Either[Nothing, A]

练习 4.6
实现Either版的map、flatMap、orElse和map2函数

 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(e) => b
    case _ => this
  }

  def map2[EE >: E, B, C](eb: Either[EE, B])(f: (A, B) => C): Either[EE, C] =
    for {
      a <- this
      b <- eb
    } yield f(a, b)

练习 4.7
对Either实现sequence和traverse,遇到错误返回第一个错误。

  def sequence[E, A](li: List[Either[E, A]]): Either[E, List[A]] = {
    def loop(n: Int, res: Either[E, List[A]]): Either[E, List[A]] = n match {
      case -1 => res
      case _ => li(n) match {
        case Left(e) => Left(e)
        case Right(a) => loop(n - 1, res.map(a :: _))  
      } 
    }
    loop(li.length - 1, Right(Nil))
  }
  
  def traverse[E, A, B](li: List[A])(f: A => Either[E, B]): Either[E, List[B]] =
    sequence(li.map(f))

你可能感兴趣的:(不是用异常来处理错误(2))