使用Scala实现Either数据结构

这个例子来源于scala圣经级教程《Functional Programming in Scala》,由于本人跟着书中的代码敲了一遍,然后写了点测试代码验证了一下正确性,所以就放在这做个备忘吧。贴出来只是为了方便自己得意,如果看不懂,但是又感兴趣的就去看原书吧偷笑偷笑偷笑

package errorhandling
//hide std library `Either`, since we are writing our own
import scala.{Either => _}

sealed trait Either[+E, +A] {

  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, AA >: A](b: => Either[EE, AA]): Either[EE, AA] =
    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] =
    for {
      a <- this
      b1 <- b
    } yield f(a, b1)
}

case class Left[+E](get: E) extends Either[E, Nothing]
case class Right[+A](get: A) extends Either[Nothing, A]

object Either {

  def mean(xs: IndexedSeq[Double]): Either[String, Double] = if (xs.isEmpty) Left("empty list") else Right(xs.sum / xs.length)

  def Try[A](a: => A): Either[Exception, A] = try Right(a)  catch { case e: Exception => Left(e) }

  def safeDiv(x: Int, y: Int): Either[Exception, Int] = try Right(x / y) catch {case e: Exception => Left(e) }

  def traverse[E, A, B](es: List[A])(f: A => Either[E, B]): Either[E, List[B]] =
    es match {
      case Nil => Right(Nil)
      case h :: t => (f(h) map2 traverse(t)(f)) (_ :: _)
    }

  def traverse_1[E, A, B](es: List[A])(f: A => Either[E, B]): Either[E, List[B]] =
    es.foldRight[Either[E, List[B]]](Right(Nil))((a, b) => f(a).map2(b)(_ :: _))


  def sequence[E, A](es: List[Either[E, A]]): Either[E, List[A]] =
    traverse(es)(x => x)



  def main(args: Array[String]): Unit = {

    val f = (x: Int, y: Int) => x / y
    val e = Either.Try(f(4, 0))
    println(e)


    val r = Either.Try(f(16, 8))
    println(r)

    val res = Try(f(16, 8)).map2(Try(f(22, 11)))((a: Int, b: Int) => a * b)
    println(res)

    val res1 = Try(f(16, 8)).map2(Try(f(22, 0)))((a: Int, b: Int) => a * b)
    println(res1)

  }

}






上述代码的运行结果是:

Left(java.lang.ArithmeticException: / by zero)
Right(2)
Right(4)
Left(java.lang.ArithmeticException: / by zero)










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值