【问题标题】:Adding fields of case classes in scala在scala中添加案例类的字段
【发布时间】:2016-09-07 09:42:48
【问题描述】:

我有以下案例类。表达式是装箱的数学运算和数字。例如 add 是表达式的子类,它递归地包含两个字段 num,这也是表达式的子类。

  abstract class Expression
  case class num (num: Int) extends Expression
  case class add  (left: Expression, right: Expression) extends Expression

  abstract class Result
  case class numericResult (v : Int) extends Result

还有其他类型的 Return,所以我无法删除案例类

Evaluate 方法应该接受表达式,将其拆箱然后执行操作并返回一个结果,即 Result 类中的框

def evaluate(expr: Expression ) : Result = {
    expr match {
      case num(n) => new numericResult(n)
      case add(l, r) => new numericResult(evaluate(l).v + evaluate(r).v) //add will never be called on imaginary numbers
      case addi(l, r) => new imaginaryResult(...)  //adds imaginary numbers

    }
}

但是当我尝试评估它时,我得到一个错误:

error: value v is not a member of Result

我如何确保 Scala 知道 l 和 r 的类型是 num 并且在评估时会给出 numericResult 而不是 Result?我可以假设如果 add evaluate(l) 和 evaluate(r) 将返回 numericResut,但 l 和 r 也可能是嵌套添加。

【问题讨论】:

  • 你为什么不从evaluate返回numericResult
  • def evaluate (expr: Expression) :numericResult = ...
  • 还有其他类型可以评估返回
  • 然后更新问题:..所以我可以假设 evaluate(l) 将始终产生 numericResult.. -- 这与您的最后评论相矛盾
  • 可以接受new numericResult(evaluate(l).asInstanceOf[numericResult].v + evaluate(r).asInstanceOf[numericResult].v) 吗?

标签: java scala types pattern-matching field


【解决方案1】:

通过它们产生的Result 的类型参数化Expressions:

abstract class Expression[T <: Result]
case class num (num: Int) extends Expression[numericResult]
case class add  (left: Expression[numericResult], right: Expression[numericResult]) extends Expression[numericResult]
case class addi (left: Expression[Result], right: Expression[Result]) extends Expression[imaginaryResult]

abstract class Result
// why lower-case? 
case class numericResult (v : Int) extends Result
case class imaginaryResult(v: Int) extends Result

def evaluate [T <: Result](expr: Expression[T] ) : T = {
  expr match {
    case num(n) => new numericResult(n)
    case add(l, r) => new numericResult(evaluate(l).v + evaluate(r).v) //add will never be called on imaginary numbers
    case addi(l, r) => new imaginaryResult(???)  //adds imaginary numbers
  }
}

【讨论】:

    【解决方案2】:

    这是在运行时验证您的评估结果的变体:

    def evaluate(expr: Expression ) : Result = {
        expr match {
          case num(n) => new numericResult(n)
          case add(l, r) => (evaluate(l), evaluate(r)) match {
               case (numericResult(l), numericResult(r)) => new numericResult(l + r)
               case (x, y) => throw new IllegalStateException(s"Numeric Results expected, got $x, $y")
          }
          case addi(l, r) => new imaginaryResult(...)  //adds imaginary numbers
        }
    }
    

    但是,为了在编译时获得类型安全,您需要考虑将Expression 类型与dependent types 互补,例如,评估的预期结果类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      • 2014-08-03
      • 1970-01-01
      • 2016-12-03
      • 1970-01-01
      • 2017-11-24
      • 2016-01-13
      相关资源
      最近更新 更多