为什么选择Scala's Try没有异常类型的类型参数



我很好奇为什么scala.util.Try没有像这样的异常类型的类型参数

abstract class Try[+E <: Throwable, +T] {
  recoverWith[U >: T](f: PartialFunction[E, Try[E, U]]): Try[E, U]
  ...
}

将有助于文档,例如

def parseInt(s: String): Try[NumberFormatException, Int]

仍然无法表达像throws SecurityException, IllegalArgumentException这样不相交的异常类型,但至少朝着这个方向迈出了一步。

这可能就是您想要的:

import scala.util.control.Exception._
import scala.util.{ Success, Failure }
def foo(x: Int): Int = x match {
  case 0 => 3
  case 1 => throw new NumberFormatException
  case _ => throw new NullPointerException
}
val Success(3) = catching(classOf[NumberFormatException]).withTry(foo(0))
val Failure(_: NumberFormatException) = catching(classOf[NumberFormatException]).withTry(foo(1))
// val neverReturns = catching(classOf[NumberFormatException]).withTry(foo(2))

请参阅scala.util.control.Exception$


然而,没有办法将Try[T]专门化为类似于假设的Try[ExcType, T];为了实现这一点,你需要像Either这样的东西(但可能需要更复杂的东西,比如scalaz./,或者,对于一个以上的异常类,Shapeless‘Coproduct):

def bar(x: Int): Either[NumberFormatException, Int] = {
  catching(classOf[NumberFormatException]).withTry(foo(x)) match {
    case Success(x) => Right(x)
    case Failure(exc) => Left(exc.asInstanceOf[NumberFormatException])
  }
}
println(bar(0)) // Right(3)
println(bar(1)) // Left(java.lang.NumberFormatException)
// println(bar(2)) // throws NullPointerException

应该可以将其概括为一个通用的帮助程序,该帮助程序可以处理任意数量的异常类型。在这种情况下,您肯定必须使用Shapeless的Coproduct和抽象过度arity的工具。不幸的是,这是一个不平凡的练习,我现在没有时间为您实现它。

最新更新