我试图按如下方式反转整数列表:
List(1,2,3,4).foldLeft(List[Int]()){(a,b) => b::a}
我的问题是,有没有办法将种子指定为某些List[_]
,其中_
是由scala的类型推理机制自动填充的类型,而不是必须指定类型如List[Int]
?
由于
答案 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)