Scala:缺少参数类型
我在Scala REPL中键入了以下内容:Scala:缺少参数类型,scala,Scala,我在Scala REPL中键入了以下内容: scala> List(1, 2, 3).toSet.subsets(2).map(_.toList) res0: Iterator[List[Int]] = non-empty iterator scala> List(1, 2, 3).toSet.subsets.map(_.toList) <console>:8: error: missing parameter type for expanded function ((
scala> List(1, 2, 3).toSet.subsets(2).map(_.toList)
res0: Iterator[List[Int]] = non-empty iterator
scala> List(1, 2, 3).toSet.subsets.map(_.toList)
<console>:8: error: missing parameter type for expanded function ((x$1) => x$1.toList)
List(1, 2, 3).toSet.subsets.map(_.toList)
scala>List(1,2,3).toSet.subsets(2).map(u.toList)
res0:Iterator[List[Int]]=非空迭代器
scala>List(1,2,3).toSet.subsets.map(u.toList)
:8:错误:缺少扩展函数的参数类型((x$1)=>x$1.toList)
列表(1,2,3).toSet.subsets.map(u.toList)
为什么第二行有错误?这是编译器中的错误还是我遗漏了什么?子集可能是另一个重载的部分应用。这似乎是编译器的问题 比较:
scala> List(1,2,3).toSet.subsets
res4: Iterator[scala.collection.immutable.Set[Int]] = non-empty iterator
scala> res4.map(_.toList)
res5: Iterator[List[Int]] = non-empty iterator
这很可能是编译器本身的问题,因为它无法进行类型推断。我以前也遇到过类似的问题 如果您快速浏览一下
Set
和的定义,它们共享相同的返回类型,因此它们都应该工作,对吗
要解决此问题,这将起到以下作用:
(List(1, 2, 3).toSet.subsets: Iterator[Set[Int]]).map(_.toList)
矛盾的是,第一个版本之所以有效,是因为应用程序子集(2)
中的子集(2)
比没有paren时更加模糊
由于方法重载,在应用程序中,编译器暂停求解toSet
的B
结果,并确定B
为Int
。因此它知道映射的参数类型
在没有参数的版本中,带有参数列表的方法不是候选方法,因为不会触发eta扩展。因此,当它键入map
应用程序时,它没有得出任何关于B
的结论,这是映射函数的输入类型
简单的解决方法是告诉它推断B
:
trait Test {
def f1 = List(1, 2, 3).to[Set].subsets.map(_.toList) // instead of .toSet
def f2 = List(1, 2, 3).toSet.subsets(2).map(_.toList)
}
原始代码上的-Ytyper debug
的输出显示了重载解析如何影响类型推断:
| | | | | | \-> => Iterator[scala.collection.immutable.Set[B]] <and> (len: Int)Iterator[scala.collection.immutable.Set[B]]
| | | | | solving for (B: ?B)
| | | | | |-- 2 : pt=Int BYVALmode-EXPRmode-POLYmode (silent: method f2 in Test)
| | | | | | \-> Int(2)
| | | | | solving for (B: ?B)
| | | | | \-> Iterator[scala.collection.immutable.Set[Int]]
让我们看看他们是否会接受库更改:
我猜.subsets
更加模糊(它可能是接受参数的版本的部分应用程序),因此类型推断工作得不太好。在任何情况下,您都可以按照编译器的指示进行编译,并提供一个显式类型:List(1,2,3).toSet.subsets.map{x:Set[Int]=>x.toList}
,但根据2.10.4 scaladoc:def subsets:Iterator[Set[A]
,def subsets(len:Int):Iterator[Set[A]]
因此,就类型而言,应该没有任何区别,对吧?在Scala中,当一个方法def子集(i:Int)(d:Double):迭代器[Set[a]
会导致对重载定义的引用不明确时,允许这些方法一起使用,这不是不一致吗?如果是Set(1,2,3).子集
它可以工作。如果你用…子集match{case x=>x.map(u.toList)}
来分解它,它也会起作用。@21不对称性在于子集
可以是子集(Int)
的部分应用,而子集(2)
不能是子集
的部分应用。(但这只是猜测)。您错误地引用了没有参数列表的子集。否则就不会有问题了
scala> implicit class ss[A](val s: Set[A]) { def ss(n: Int) = s subsets n ; def ss = s.subsets }
defined class ss
scala> List(1, 2, 3).toSet.ss.map(_.toList)
res1: Iterator[List[Int]] = non-empty iterator