我想通过一个自定义的通用unapply函数来压缩我的求值程序,该函数计算参数并在成功时返回值。
但这失败了,错误为error: not found: type Eval
任何实现这一目标的方法?我看过typetags,implicit conversions for unapply methods,但我看不出如何将它们整合到这个问题中。如何正确定义Eval?
object Test { case class Context() trait Expr trait Literal[T] extends Expr{ def value : T } case class IntLiteral(value: Int) extends Literal[Int] case class StringLiteral(value: Int) extends Literal[Int] case class Plus(e: Expr, f: Expr) extends Expr object Eval { // Here I want the magic unapply to evaluate the expression. def unapply[T](e: Expr)(implicit gctx: Context): Option[T] = { eval(e) match { case e: Literal[T] => Some(e.value) case _ => None } } } def eval(e: Expr)(implicit c: Context): Expr = e match { case Plus(Eval[Int](i), Eval[Int](j)) => IntLiteral(i+j) // Fails here. case IntLiteral(i) => e case StringLiteral(s) => e } eval(Plus(Plus(IntLiteral(1),IntLiteral(2)),IntLiteral(3)))(Context()) }
答案 0 :(得分:1)
Eval[Int](...)
根本不是合法模式,因此您无法获得此语法。您可以使Eval
本身通用,并为您想要的类型创建实例:
object Test {
case class Context()
trait Expr
trait Literal[T] extends Expr {
def value: T
}
case class IntLiteral(value: Int) extends Literal[Int]
case class StringLiteral(value: Int) extends Literal[Int]
case class Plus(e: Expr, f: Expr) extends Expr
case class Eval[T]() {
def unapply(e: Expr)(implicit gctx: Context): Option[T] = {
eval(e) match {
case e: Literal[T] => Some(e.value)
case _ => None
}
}
}
val IntEval = Eval[Int]()
def eval(e: Expr)(implicit c: Context): Expr = e match {
case Plus(IntEval(i), IntEval(j)) => IntLiteral(i + j)
case IntLiteral(i) => e
case StringLiteral(s) => e
}
println(eval(Plus(Plus(IntLiteral(1), IntLiteral(2)), IntLiteral(3)))(Context()))
}
但请注意,这不会检查文字的类型!如果您也想要这一点,则需要ClassTag
,这只允许匹配: T
,而不是: Literal[T]
:
object Test {
case class Context()
trait Expr
case class Literal[T](value: T) extends Expr // or case class Literal(value: Any)
case class Plus(e: Expr, f: Expr) extends Expr
case class Eval[T]()(implicit tag: scala.reflect.ClassTag[T]) {
def unapply(e: Expr)(implicit gctx: Context): Option[T] = {
eval(e) match {
case Literal(value: T) => Some(value)
case _ => None
}
}
}
val IntEval = Eval[Int]()
def eval(e: Expr)(implicit c: Context): Expr = e match {
case Plus(IntEval(i), IntEval(j)) => Literal(i + j)
case e: Literal[_] => e
}
println(eval(Plus(Plus(Literal(1), Literal(2)), Literal(3)))(Context()))
}