假设我已经定义了这些类(这是我的代码的简化版本)
sealed trait Expression
trait ExpressionA extends Expression
trait ExpressionB extends Expression
case class OperationA(op: String, a: ExpressionA, b:ExpressionA) extends ExpressionA
case class OperationB(op: String, a: ExpressionB, b:ExpressionB) extends ExpressionB
case class ComparisonB(op: String, a: ExpressionA, b:ExpressionA) extends ExpressionB
case class VariableA(op: String, a: ExpressionA) extends ExpressionA
然后我想替换 VariableA 类中的给定字符串 这样我就可以写
def replace(exp: ExpressionB, operation: String => String): ExpressionB = exp match {
case ComparisonB(op, a, b) => ComparisonB(op, replace(a, operation), replace(b, operation))
case OperationB(op, a, b) => OperationB(op, replace(a, operation), replace(b, operation))
}
def replace(exp: ExpressionA, operation: String => String): ExpressionA = exp match {
case OperationA(op, a, b) => OperationA(op, replace(a, operation), replace(b, operation))
case VariableA(name) => VariableA(operation(name))
}
但我想将这两个函数合并为一个,并具有通用类型。
这是我尝试过的
def replace[T <: Expression](exp:T, operation: String => String):T = exp match {
case ComparisonB(op, a, b) => ComparisonB(op, replace(a, operation), replace(b, operation))
case OperationB(op, a, b) => OperationB(op, replace(a, operation), replace(b, operation))
case OperationA(op, a, b) => OperationA(op, replace(a, operation), replace(b, operation))
case VariableA(name) => VariableA(operation(name))
}
我收到错误
Expression of type ExpressionA does not conform to expected type T
尽管理论上它始终与输入具有相同的类型。所以我不知道我的代码有什么问题,是否缺少一些隐式内容,或者执行方法错误?
最佳答案
如果您希望 replace
的返回类型取决于 exp
的值(即 exp
是否匹配特定模式),那么实际上您想要一个polymorphic功能。
trait Replacer[T <: Expression] {
def replace(exp: T, operation: String => String): T
}
object Replacer {
implicit val exprA: Replacer[ExpressionA] =
(exp: ExpressionA, operation: String => String) => exp match {
case OperationA(op, a, b) => OperationA(op, replace(a, operation), replace(b, operation))
case VariableA(name) => VariableA(operation(name))
}
implicit val exprB: Replacer[ExpressionB] =
(exp: ExpressionB, operation: String => String) => exp match {
case ComparisonB(op, a, b) => ComparisonB(op, replace(a, operation), replace(b, operation))
case OperationB(op, a, b) => OperationB(op, replace(a, operation), replace(b, operation))
}
}
def replace[T <: Expression](exp: T, operation: String => String)(implicit replacer: Replacer[T]): T =
replacer.replace(exp, operation)
关于scala - 如何在 Scala 中参数化具有继承类型的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48475187/