问题描述
我有一个带参数的类型别名,我想从一个方法返回不同参数类型的实例:
I have a type alias with parameter and I would like to return the instance of different parameter types from a method:
type TC[T] = (ClassTag[T], Option[T])
def gen(x: Int): TC[_] = x match {
case 0 => (classTag[Int], Option[Int](0))
case _ => (classTag[String], Option[String](""))
}
这不起作用,并给我错误:
This does not work and gives me error:
我尝试使用Any
代替通配符_
,但仍然无法正常工作:
And I tried to use Any
instead of wildcard _
, and it still does not work:
def gen(x: Int): TC[Any]
如何实现?
推荐答案
最好返回特定类型,而不是存在类型.如果要gen
根据其参数返回不同的类型,则实际上gen
是多态函数.使用类型类和单例类型尝试以下方法.
It's better to return specific type rather than existential. If you want gen
to return different types depending on its argument then actually gen
is a polymorphic function. Try the following approach with type class and singleton types.
type TC[T] = (ClassTag[T], Option[T])
trait Gen[X <: Int] {
type Out
def apply(x: X): Out
}
trait LowPriorityGen {
type Aux[X <: Int, Out0] = Gen[X] { type Out = Out0 }
def instance[X <: Int, Out0](f: X => Out0): Aux[X, Out0] = new Gen[X] {
override type Out = Out0
override def apply(x: X): Out0 = f(x)
}
implicit def default[X <: Int : ValueOf]: Aux[X, TC[String]] = instance(_ => (classTag[String], Option[String]("")))
}
object Gen extends LowPriorityGen {
implicit val zero: Aux[0, TC[Int]] = instance(_ => (classTag[Int], Option[Int](0)))
}
def gen[X <: Int with Singleton](x: X)(implicit g: Gen[X]): g.Out = g(x)
gen(0) //(Int,Some(0))
gen(1) //(java.lang.String,Some())
原因类似于中的原因.上一个问题. ClassTag
和Option
的方差不同.
Reasons are similar to those in the previous question. ClassTag
and Option
have different variance.
尝试
type TC[T] = (ClassTag[_ <: T], Option[T])
def gen(x: Int): TC[_] = x match {
case 0 => (classTag[Int], Option[Int](0))
case _ => (classTag[String], Option[String](""))
}
即使您不能在类型中编码所需的属性,您仍然可以在编译时使用模式匹配右侧的check
对其进行检查.
Even if you can't encode desirable property in types you still can check it at compile time with check
in right hand side of pattern matching.
def gen(x: Int): (ClassTag[_], Option[_]) = x match {
case 0 => check(classTag[Int], Option[Int](0))
case _ => check(classTag[String], Option[String](""))
}
def check[T](classTag: ClassTag[T], option: Option[T]): (ClassTag[T], Option[T]) = (classTag, option)
这篇关于如何返回通配符泛型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!