Generics 与泛型类型的值进行模式匹配
我正在编写基于树的表达式计算器,在类型擦除方面遇到了一些问题 这棵树看起来像Generics 与泛型类型的值进行模式匹配,generics,scala,pattern-matching,Generics,Scala,Pattern Matching,我正在编写基于树的表达式计算器,在类型擦除方面遇到了一些问题 这棵树看起来像 sealed abstract class Node[+T] case class Var[+T](name:String) extends Node[T] /* SNIP */ 评估者是 def eval[T](node:Node[T], context:Map[String, Any]):Option[T] = node match { case Var(name) => context.get(nam
sealed abstract class Node[+T]
case class Var[+T](name:String) extends Node[T]
/* SNIP */
评估者是
def eval[T](node:Node[T], context:Map[String, Any]):Option[T] = node match {
case Var(name) => context.get(name) match {
case Some(value:T) => Some(value)
case _ => None
}
/* SNIP */
}
代码可以编译,但是Var
节点上的类型检查不起作用。所以这个测试失败了:
class ContextEvaluatorTest extends FunSuite with ShouldMatchers {
test("evaluation with type mismatch") {
ContextEvaluator.eval(Var[Int]("a"), Map("a" -> "not int")) should equal (None)
}
}
错误消息是
org.scalatest.TestFailedException: Some(not int) did not equal None
这种情况看起来像是清单的用例,但我无法正确添加它们。这似乎有效:
def eval[T:ClassManifest](node:Node[T], context:Map[String, Any]):Option[T] = node match {
case Var(name) => context.get(name) match {
case Some(value:T) if classManifest[T].erasure.isInstance(value) => Some(value)
case _ => None
}
case _ => None
}
但是请注意,T
必须是一个简单类型,AFAIKClassManifest
无法区分List[Int]
和List[String]
之类的内容。可能Manifest
可以做到这一点,但是调查要比在底层类上调用isInstance
复杂得多。这似乎有效:
def eval[T:ClassManifest](node:Node[T], context:Map[String, Any]):Option[T] = node match {
case Var(name) => context.get(name) match {
case Some(value:T) if classManifest[T].erasure.isInstance(value) => Some(value)
case _ => None
}
case _ => None
}
但是请注意,
T
必须是一个简单类型,AFAIKClassManifest
无法区分List[Int]
和List[String]
之类的内容。可能Manifest
可以做到这一点,但是调查要比在底层类上调用isInstance
复杂得多。它不起作用,因为t
被擦除了。这意味着模式匹配中的value:T
没有意义。事实上,编译器应该警告您这一点
您将不得不求助于使用清单来进行测试。请参见的示例。它不起作用,因为
t
被擦除。这意味着模式匹配中的value:T
没有意义。事实上,编译器应该警告您这一点
您将不得不求助于使用清单来进行测试。请参见的示例