Scalac无法编译通过TraversableOnce [_]和元素类型

时间:2015-11-04 00:06:59

标签: scala generics

我有一个函数的用例,它针对任何TraversableOnce[T] T的任何类型进行参数化。我试着用

def test[T, F[_] <: TraversableOnce[_]](ts: F[T]): Unit = {
  ts.foldLeft("")((acc: String, t: T) => if (acc.isEmpty) t.toString else acc + "," + t.toString)
}

但Scalac以一种我发现奇怪的方式抱怨:

<console>:8: error: type mismatch;
 found   : (String, T) => String
 required: (String, _$1) => String
           ts.foldLeft("")((acc: String, t: T) => if (acc.isEmpty) t.toString else acc + "," + t.toString)

现在我知道我可以使用约束F[T] <: TraversableOnce[T],但我想理解为什么Scalac无法使用我刚刚编写的函数版本。 ts的类型为F[T],因此foldLeft的第二个参数的类型应为(String, T) => String(String, _$1) => String的{​​{1}}的类型未知。这里发生了什么?

2 个答案:

答案 0 :(得分:3)

这样的签名:

def test[T, F[_] <: TraversableOnce[_]](ts: F[T]): Unit

与此类签名不同:

def test[T, F[X] <: TraversableOnce[X]](ts: F[T]): Unit

在后一种情况下,你说F“F是一个带有单一类型参数的类型,它是TraversableOnce的子类,只要F和TraversableOnce具有相同的类型参数。”带下划线的版本意味着更像“F是具有单个参数的类型,它是TraversableOnce [Any]的子类”。

意义不同的原因是第一个版本中的两个下划线是不相关的。在该签名中,TraversableOnce[_]TraversableOnce[Any]相同,而在F[_]中,下划线充当自由变量。这相当于这样说:

def test[T, F[X] <: TraversableOnce[_]](ts: F[T]): Unit

此处,X是一个自由变量,不会绑定到F[X]之外的任何内容。

答案 1 :(得分:1)

您尚未将类型参数绑定到可遍历的类型参数。

您正在传递一个需要T的函数,但是不会限制遍历的未知类型参数。

scala> def f[T, F[T] <: TraversableOnce[T]](ts: F[T]) = ts.foldLeft("") _
f: [T, F[T] <: TraversableOnce[T]](ts: F[T])((String, T) => String) => String

scala> def f[T, F[_] <: TraversableOnce[_]](ts: F[T]) = ts.foldLeft("") _
f: [T, F[_] <: TraversableOnce[_]](ts: F[T])((String, Any) => String) => String

符号TO[_]TO[t] forSome { type t }的简写,其中_$1是您可遍历的t