Scala列表与泛型的模式匹配 [英] Pattern match of scala list with generics
问题描述
我上课
case class MyClass[T](values: List[T])
并且我正在尝试创建一个函数,该函数将根据T的类型返回一个值
and I'm trying to create a function which will return a value based on the type of T
def myFunc: T = values match {
case v: List[Boolean] => false
case v: List[MyType] => MyType.defaultVal
case _ => throw new Exception("unsupported type")
}
但是,我收到编译错误:
However, I get compilation errors:
布尔类型的表达不符合预期的类型T
Expression of type Boolean doesn't conform to expected type T
MyType.defaultVal.type类型的表达与预期的T类型不一致
Expression of type MyType.defaultVal.type doesn't conform to expected type T
我想我可以通过创建一个抽象类和子类来解决此问题,但我宁愿不这样做.还有其他解决方法吗?
I guess I can solve this by creating an abstract class ans subclasses, but I'd rather not do it this way. Is there any other way to solve this?
推荐答案
问题是模式匹配主要在运行时执行,类型在编译时解析.由于类型擦除,case v: List[Boolean] => ???
并不比case v: List[_] => ???
好.在case v: List[Boolean] => ...
行中,编译器不知道T =:= Boolean
.模式匹配无法在不同情况下返回不同的类型.
The thing is that pattern matching is performed mostly at runtime and types are resolved at compile time. Because of type erasure case v: List[Boolean] => ???
is not better than case v: List[_] => ???
. In the line case v: List[Boolean] => ...
compiler doesn't know that T =:= Boolean
. Pattern matching can't return different types from different cases.
因此,您可以使用类型标签进行样式匹配并强制转换
So you can either pattern match with type tags and casting
case class MyClass[T](values: List[T]) {
import reflect.runtime.universe.{TypeTag, typeOf}
def myFunc(implicit typeTag: TypeTag[T]): T = values match {
case v: List[Boolean] if typeOf[T] <:< typeOf[Boolean] => false.asInstanceOf[T]
case v: List[MyType] if typeOf[T] <:< typeOf[MyType] => MyType.defaultVal.asInstanceOf[T]
case _ => throw new Exception("unsupported type")
}
}
或者使用类型类(或多态函数)更安全地进行此操作
or do this more type-safely with a type class (or polymorphic function)
case class MyClass[T](values: List[T]) {
def myFunc(implicit myFuncInstance: MyFunc[T]): T = myFuncInstance(values)
}
trait MyFunc[T] {
def apply(values: List[T]): T
}
object MyFunc {
implicit val booleanMyFunc: MyFunc[Boolean] = new MyFunc[Boolean] {
override def apply(values: List[Boolean]): Boolean = false
}
implicit val myTypeMyFunc: MyFunc[MyType] = new MyFunc[MyType] {
override def apply(values: List[MyType]): MyType = MyType.defaultVal
}
}
这篇关于Scala列表与泛型的模式匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!