本文介绍了Scala:缺少参数类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Scala-REPL 中输入了以下内容:

I typed the following into the 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)

为什么第二行出现错误?这是编译器中的错误还是我遗漏了什么?

Why am I getting an error for the second line? Is this a bug in the compiler or am I missing something?

推荐答案

矛盾的是,第一个版本有效,因为应用程序 subsets(2) 中的 subsets 就是这样比没有括号更模棱两可.

Paradoxically, the first version works because subsets in the application subsets(2) is, as it were, more ambiguous than without parens.

因为方法重载,在应用程序中,编译器暂停求解toSetB结果,决定BInt.所以它知道 map 需要什么参数类型.

Because the method is overloaded, in the application, the compiler pauses to solve for the B result of toSet, and decides that B is Int. So it knows what param type is expected for the map.

在没有括号的版本中,带参数列表的方法不是候选,因为没有触发eta-expansion.所以当它输入map应用程序时,它并没有得出任何关于B的结论,它是映射函数的输入类型.

In the version without parens, the method with a parameter list is not a candidate, because eta-expansion is not triggered. So when it types the map application, it has not drawn any conclusions about B, which is the input type to the mapping function.

简单的解决方法是告诉它推导B:

The easy fix is to tell it to deduce 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 在原始代码上的输出显示了重载解析是如何进行类型推断的:

The output of -Ytyper-debug on the original code shows how overload resolution gooses type inference:

|    |    |    |    |    |    \-> => 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]]

另一种解决方法是通过扩展方法:

Another workaround is to go through an extension method:

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

让我们看看他们是否会改变图书馆:

Let's see if they'll take the library change:

https://github.com/scala/scala/pull/4270

这篇关于Scala:缺少参数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 00:51