我有以下功能
def f[T](l:List[T], v:T)
这适用于
没有错误f(List(1,2,3), "this is a string")
即使两个参数中的T不相同。是否有可能重写函数,以便编译器在两个参数中T不相同时给出错误? (我不能依赖用户在函数f [Int]中明确指定类型)
[为可怕的头衔道歉]
答案 0 :(得分:3)
类型统一仅在参数列表中发生。您可以使用单独的参数列表,但这只能确保v.type <:< T
,而不是v.type =:= T
。
def f[T](l:List[T])(v:T): List[T] = v :: l
f(List(1,2,3))("this is a string")
Error:(81, 20) type mismatch;
found : String("this is a string")
required: Int
f(List(1,2,3))("this is a string")
另一种选择是使用隐式,但它需要一个类型转换:
def f[T, U](l: List[T], v: U)(implicit ev: T =:= U): List[T] =
v.asInstanceOf[T] :: l
val l1 = List("a", "b", "c")
val l2: List[Any] = List("a", "b", "c")
val s1 = "d"
val s2: Any = "d"
f(l1, s1) // compiles
f(l2, s2) // compiles
f(l1, s2) // Cannot prove that String =:= Any.
f(l2, s1) // Cannot prove that Any =:= String.
答案 1 :(得分:0)
首先,Scala通过查找可以概括为T的常见超类型来处理这种情况下的类型类。在您的示例中,您有Int
和String
,其中普通超级为{{1 }}。因此,使用Any
调用def f[T](l:List[T], v:T): T = v
会产生f(List(1, 2, 3), "scala")
。
现在,根据所需的行为,有几种方法可以处理。这个问题包含相反问题的简洁答案(确保类型差异)Enforce type difference。另一方面,您可以决定使用Any = "scala"
或引入一些允许您区分类型的隐含。然而,无论采用何种方法,您的方法都可能需要遵循定义ClassTag
并实施上述类型保护之一。