采用隐式 CanBuildFrom 的方法不适用于 eta-expansion?

Tom*_*icz 5 scala scala-collections

我有以下方法:

def firstAndLast[CC, A, That](seq: CC)(implicit asSeq: CC => Seq[A], cbf: CanBuildFrom[CC, A, That]): That = {
  val b = cbf(seq)
  b += seq.head
  b += seq.last
  b.result
}
Run Code Online (Sandbox Code Playgroud)

请参阅:使用Seq[T] 返回 String 而不是 Seq[Char] 的方法以了解基本原理。在第一种情况下它就像一个魅力,但在第二种情况下无法编译:

List("abc", "def") map {firstAndLast(_)}
List("abc", "def") map firstAndLast
Run Code Online (Sandbox Code Playgroud)

给予:

error: No implicit view available from CC => Seq[A].
List("abc", "def") map firstAndLast
Run Code Online (Sandbox Code Playgroud)

知道如何改进此声明以避免额外包装吗?似乎 eta-expansion 是问题所在(?)

Dan*_*ral 1

尽管它们看起来很相似,但它们是不同的:

List("abc", "def") map {firstAndLast(_)}
// { x => firstAndLast(x) }

List("abc", "def") map firstAndLast
// firstAndLast, if it happened to be a function
Run Code Online (Sandbox Code Playgroud)

现在,请注意编译器如何轻松地输入x第一种情况。在第二种情况下,它试图找出如何(seq: CC)(implicit asSeq: CC => Seq[A], cbf: CanBuildFrom[CC, A, That])解释为Function1[String, ???],但它失败了,因为缺少很多信息——即类型参数。

换句话说,在第一种情况下,编译器首先键入x,因此,CC,然后尝试计算其余部分。在第二种情况下,编译器试图同时找出所有类型参数。