Scala中有什么办法可以拥有“临时” ADT?

时间:2019-07-07 19:08:08

标签: scala algebraic-data-types

我想完全摆脱Scala代码中的异常,而是从如下方法返回显式/类型化结果(ADT):

class SomeService {

  def method1: Method1Result = ...
}

object SomeService {

  trait Method1Result
  object Method1Result {
    case class Success(id: String) extends Method1Result
    case object AlreadyExists  extends Method1Result
    case object Error extends Method1Result
  }
}

但是,正如您所看到的,它太样板了……

理想情况下,我想要这样的东西:

class SomeService {
  def method1: Success(id: String) | AlreadyExists | Error
}

如您所见,ADT是在method1

的返回类型中定义的

可能有一些编译器插件或注释处理库 允许编写此类代码并在后台生成ADT?

或者如果我想从方法中返回键入的结果,Scala的最佳实践是什么?

2 个答案:

答案 0 :(得分:3)

您可以使用Coproduct中的shapeless。不确定在应用程序级代码中走这条路是否有意义。

import shapeless.{:+:, CNil, Coproduct}

case class Success(id: String)
case class AlreadyExists
case class Error
type AllThree = Success :+: AlreadyExists :+: Error :+: CNil

或者您可以创建自己的类型,例如 Either3[A, B, C]Either4[A,B,C,D],...并用一些样板来解决。

答案 1 :(得分:2)

Scala 3可能会带来union types,我们将能够准确地写出。您可以通过选择Dotty编译器目标在Scastie中进行尝试。

例如https://scastie.scala-lang.org/19tnxxxyTua2utD6QCocaw

object Main extends App {  
  case class Success(id: String)
  case object AlreadyExists
  case object Error

  def method1: Success | AlreadyExists.type | Error.type = AlreadyExists

  println(method1)
}

输出

AlreadyExists