Method taking implicit CanBuildFrom does not work with eta-expansion?

ぃ、小莉子 提交于 2019-12-01 05:08:56

问题


I have a following method:

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
}

See: Method taking Seq[T] to return String rather than Seq[Char] for rationale. It works like a charm in the first case but fails to compile in the second:

List("abc", "def") map {firstAndLast(_)}
List("abc", "def") map firstAndLast

Giving:

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

Any idea how to improve this declaration to avoid extra wrapping? Seems like eta-expansion is the problem (?)


回答1:


Though they look similar, these are different things:

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

List("abc", "def") map firstAndLast
// firstAndLast, if it happened to be a function

Now, note how the compiler can easily type x in the first case. In the second case, it is trying to figure out how (seq: CC)(implicit asSeq: CC => Seq[A], cbf: CanBuildFrom[CC, A, That]) might be interpreted as Function1[String, ???], and it is failing because there's a lot of information missing -- namely, the type parameters.

In other words, in the first case, the compiler first types x, and, therefore, CC, and then tries to figure out the rest. In the second case, the compiler is trying to figure out all of the type parameters at the same time.




回答2:


Not a full answer to your question, but I’ve just noticed that this works:

List("abc", "def") map firstAndLast[String, Char, String]

It then means that the type inferencer is having trouble determining the right type parameters for firstAndLast, but I wouldn’t know how to fix it…



来源:https://stackoverflow.com/questions/10774284/method-taking-implicit-canbuildfrom-does-not-work-with-eta-expansion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!