我在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 ((x$1) => x$1.toList)
List(1, 2, 3).toSet.subsets.map(_.toList)
为什么我在第二行收到错误?这是编译器中的错误还是我遗漏了什么?
答案 0 :(得分:4)
这很可能是编译器问题本身无法进行类型推断。我之前遇到过类似的问题。
如果您快速查看Set
的{{3}}和subsets()的定义,它们会共享相同的返回类型,因此它们都应该正常工作,对吗?
要解决问题,这将有效:
(List(1, 2, 3).toSet.subsets: Iterator[Set[Int]]).map(_.toList)
答案 1 :(得分:3)
矛盾的是,第一个版本有效,因为应用程序subsets
中的subsets(2)
实际上比没有parens时更加模糊。
由于该方法已重载,因此在应用程序中,编译器暂停以求解B
的{{1}}结果,并确定toSet
为B
。因此它知道Int
预期的param类型。
在没有parens的版本中,带参数列表的方法不是候选者,因为不会触发eta-expansion。因此,当它键入map
应用程序时,它没有得出关于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]]
另一种解决方法是通过扩展方法:
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
让我们看看他们是否会改变图书馆:
答案 2 :(得分:0)
子集可以部分应用其他过载。
答案 3 :(得分:0)
这似乎是编译器问题。
比较
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