折叠左一行的类型推断?

时间:2012-11-21 06:46:43

标签: scala type-inference fold

我试图按如下方式反转整数列表:

List(1,2,3,4).foldLeft(List[Int]()){(a,b) => b::a}

我的问题是,有没有办法将种子指定为某些List[_],其中_是由scala的类型推理机制自动填充的类型,而不是必须指定类型如List[Int]

由于

2 个答案:

答案 0 :(得分:5)

更新:在阅读了有关Scala类型推断的更多信息后,我找到了更好的答案。 This article这与Scala类型推断的局限性有关:

  

Scala中的类型信息从函数参数流向其结果[...],从参数列表的左侧到右侧,以及从头到尾的语句。这与具有完整类型推断的语言形成对比,其中(粗略地说)类型信息在所有方向上不受限制地流动。

所以问题是Scala的类型推断相当有限。 first 查看第一个参数列表(在您的情况下为列表),然后在第二个参数列表(函数)中查看然后。但它不会回去。

这就是为什么这个

List(1,2,3,4).foldLeft(Nil){(a,b) => b::a}

也不是这个

List(1,2,3,4).foldLeft(List()){(a,b) => b::a}

会奏效。为什么?首先,foldLeft的签名定义为:

 foldLeft[B](z: B)(f: (B, A) => B): B 

因此,如果您使用Nil作为第一个参数z,编译器会将Nil.type分配给类型参数B。如果您使用List(),编译器将List[Nothing]用于B

现在,完全定义了第二个参数f的类型。在你的情况下,它是

(Nil.type, Int) => Nil.type

(List[Nothing], Int) => List[Nothing]

在这两种情况下,lambda表达式(a, b) => b :: a都无效,因为它的返回类型被推断为List[Int]


请注意,上面的粗体部分表示“参数列表”而不是“参数”。这篇文章后来解释说:

  

类型信息不会在参数列表中从左到右流动,只能从左到右参数列表。

如果你有一个带有单个参数列表的方法,情况会更糟。

答案 1 :(得分:4)

我知道的唯一方法是

scala> def foldList[T](l: List[T]) = l.foldLeft(List[T]()){(a,b) => b::a}
foldList: [T](l: List[T])List[T]

scala> foldList(List(1,2,3,4))
res19: List[Int] = List(4, 3, 2, 1)

scala> foldList(List("a","b","c"))
res20: List[java.lang.String] = List(c, b, a)