如何将元组的扩展类型传递给不变的泛型函数?
How to pass extential type of tuple to invariant generic function?
我有一个扩展类型的元组,我想将它传递给一个泛型函数(我在这个例子中使用了 ClassTag,但它是一个自定义类型 class,具有不变的类型参数):
type TC = (ClassTag[T], Option[T]) forSome {type T}
def foo[T](ct: ClassTag[T], o: Option[T]) = {}
val tc: TC = (classTag[String], Option[String](null))
foo(tc._1, tc._2)
这给我错误:
error: type mismatch;
found : scala.reflect.ClassTag[T]
required: scala.reflect.ClassTag[Any]
Note: T <: Any, but trait ClassTag is invariant in type T.
You may wish to investigate a wildcard type such as _ <: Any
. (SLS 3.2.10)
foo(tc._1, tc._2)
我想确保两个参数的类型 ct
和 o
使用相同的参数类型 T 我认为扩展类型应该确保这一点,但它似乎不起作用。
然而,如果我不使用元组而只使用 ClassTag,它工作正常:
type TC = ClassTag[T] forSome {type T}
def foo[T](ct: ClassTag[T]) = {}
val tc: TC = classTag[String]
foo(tc)
所以之前ClassTag不变性的错误没有意义
为什么我使用元组时不起作用?我怎样才能让它发挥作用?
因为 val tc: TC = classTag[String], Option[String](null))
tc._1
有类型 ClassTag[_]
(不同于任何 ClassTag[T]
例如 ClassTag[Any]
因为 ClassTag
是不变的), tc._2
的类型为 Option[_]
,与 Option[Any]
相同,因为 Option
是协变的
implicitly[Option[_] =:= Option[Any]]
implicitly[Option[Any] =:= Option[_]]
An existential type forSome { }
where </code> contains a clause type <code>[tps]>:<:
is equivalent to the type ′ forSome { }
where ′
results from </code> by replacing every covariant occurrence of <code>
in </code> by <code>
and by replacing every contravariant occurrence of
in </code> by <code>
.
https://www.scala-lang.org/files/archive/spec/2.13/03-types.html#existential-types
所以在
def foo[T](ct: ClassTag[T], o: Option[T]) = {}
foo(tc._1, tc._2)
类型不匹配。 Any
和 _
(又名任意 T
)是不同的类型。
尝试使用通用量化而不是存在
type TC[T] = (ClassTag[T], Option[T])
def foo[T](ct: ClassTag[T], o: Option[T]) = {}
val tc: TC[String] = (classTag[String], Option[String](null))
foo(tc._1, tc._2)
我有一个扩展类型的元组,我想将它传递给一个泛型函数(我在这个例子中使用了 ClassTag,但它是一个自定义类型 class,具有不变的类型参数):
type TC = (ClassTag[T], Option[T]) forSome {type T}
def foo[T](ct: ClassTag[T], o: Option[T]) = {}
val tc: TC = (classTag[String], Option[String](null))
foo(tc._1, tc._2)
这给我错误:
error: type mismatch; found : scala.reflect.ClassTag[T] required: scala.reflect.ClassTag[Any] Note: T <: Any, but trait ClassTag is invariant in type T. You may wish to investigate a wildcard type such as
_ <: Any
. (SLS 3.2.10) foo(tc._1, tc._2)
我想确保两个参数的类型 ct
和 o
使用相同的参数类型 T 我认为扩展类型应该确保这一点,但它似乎不起作用。
然而,如果我不使用元组而只使用 ClassTag,它工作正常:
type TC = ClassTag[T] forSome {type T}
def foo[T](ct: ClassTag[T]) = {}
val tc: TC = classTag[String]
foo(tc)
所以之前ClassTag不变性的错误没有意义
为什么我使用元组时不起作用?我怎样才能让它发挥作用?
因为 val tc: TC = classTag[String], Option[String](null))
tc._1
有类型 ClassTag[_]
(不同于任何 ClassTag[T]
例如 ClassTag[Any]
因为 ClassTag
是不变的), tc._2
的类型为 Option[_]
,与 Option[Any]
相同,因为 Option
是协变的
implicitly[Option[_] =:= Option[Any]]
implicitly[Option[Any] =:= Option[_]]
An existential type
forSome { }
where</code> contains a clause type <code>[tps]>:<:
is equivalent to the type′ forSome { }
where′
results from</code> by replacing every covariant occurrence of <code>
in</code> by <code>
and by replacing every contravariant occurrence ofin
</code> by <code>
.
https://www.scala-lang.org/files/archive/spec/2.13/03-types.html#existential-types
所以在
def foo[T](ct: ClassTag[T], o: Option[T]) = {}
foo(tc._1, tc._2)
类型不匹配。 Any
和 _
(又名任意 T
)是不同的类型。
尝试使用通用量化而不是存在
type TC[T] = (ClassTag[T], Option[T])
def foo[T](ct: ClassTag[T], o: Option[T]) = {}
val tc: TC[String] = (classTag[String], Option[String](null))
foo(tc._1, tc._2)