使用T上较高类型的多个参数限制通用函数fun [T]正好为T.

时间:2016-08-03 07:13:34

标签: scala

我有以下功能

def f[T](l:List[T], v:T)

这适用于

没有错误
f(List(1,2,3), "this is a string")

即使两个参数中的T不相同。是否有可能重写函数,以便编译器在两个参数中T不相同时给出错误? (我不能依赖用户在函数f [Int]中明确指定类型)

[为可怕的头衔道歉]

2 个答案:

答案 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的常见超类型来处理这种情况下的类型类。在您的示例中,您有IntString,其中普通超级为{{1 }}。因此,使用Any调用def f[T](l:List[T], v:T): T = v会产生f(List(1, 2, 3), "scala")

现在,根据所需的行为,有几种方法可以处理。这个问题包含相反问题的简洁答案(确保类型差异)Enforce type difference。另一方面,您可以决定使用Any = "scala"或引入一些允许您区分类型的隐含。然而,无论采用何种方法,您的方法都可能需要遵循定义ClassTag并实施上述类型保护之一。