【问题标题】:How to refactor a function that throws exceptions with Scalaz or Cats如何使用 Scalaz 或 Cats 重构抛出异常的函数
【发布时间】:2016-06-20 06:20:11
【问题描述】:

这是我之前question的后续:

假设我正在重构这样的函数:

def check(ox: Option[Int]): Unit = ox match {
  case None => throw new Exception("X is missing")
  case Some(x) if x < 0 => throw new Exception("X is negative")
  case _ => ()
}

我正在编写一个新的纯函数 doCheck 以返回 Unit 或异常。

case class MissingX() extends Exception("X is missing")
case class NegativeX(x: Int) extends Exception(s"$x is negative")

import scalaz._, Scalaz._

type Result[A] = Excepiton \/ A

def doCheck(ox:Option[Int]): Result[Unit] = for {
  x <- ox toRightDisjunction MissingX()
  _ <- (x >= 0) either(()) or NegativeX(x)
} yield ()

然后从check调用它

def check(ox:Option[Int]): Unit = doCheck(ox) match {
  case -\/(e) => throw e
  case _ => ()
}

这有意义吗?像这样实现doCheck会更好吗?

def doCheck(ox:Option[Int]): Result[Int] = for {
  x1 <- ox toRightDisjunction MissingX()
  x2 <- (x1 >= 0) either(x1) or NegativeX(x1)
} yield x2

如何用cats实现它?

【问题讨论】:

  • 为什么还在check中抛出异常?
  • @PeterNeyens 我不想更改check之外的所有代码。

标签: scala refactoring scalaz scala-cats


【解决方案1】:

你会在猫身上做同样的事情,只有猫本身没有 Boolean =&gt; Xor[A, B] 语法,就像来自 scalaz 的 either () or () 一样。

import cats.data.Xor
import cats.implicits._

def doCheck(ox: Option[Int]): Xor[Exception, Unit] =
  ox.toRightXor(MissingX()).flatMap(x => if(x > 0) ().right else NegativeX(x).left)

您可以使用mouse,它为猫提供了类似的语法助手:

import com.github.benhutchison.mouse.boolean._

ox.toRightXor(MissingX()).flatMap(x => (x > 0).toXor(NegativeX(x), ()))

Xor 也有 ensure 方法来做这样的事情,但如果谓词不成立,它不会让你访问元素。如果你不需要x 来代替NegativeX,你可以这样写:

ox.toRightXOr(MissingX()).ensure(Negative())(_ > 0).void

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 2015-08-26
    • 2011-11-04
    • 1970-01-01
    • 2012-10-28
    • 2018-04-21
    相关资源
    最近更新 更多