Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inferring parameter type for a lambda (again!)

Tags:

lambda

scala

I am wondering why does this not work (missing parameter type)?

 Seq(1,2,3).toSet.map(_ + 1)

but this does:

 val foo = Seq(1,2,3).toSet
 foo.map(_ + 1)

as well as this: (3)

  Seq(1,2,3).toSet[Int].map(_ + 1)

or this:

  Seq(1,2,3).toList.map(_ + 1)

What is special about toSet that makes it loose the type in the first case, but not in the second?

like image 574
Dima Avatar asked May 02 '19 15:05

Dima


1 Answers

An educated guess:

def toSet[B :> A]: Set[B]

vs

def toList: List[A]

For some reason toSet is parametric - if you split toSet and map into two statements, then in first case compiler will have to assume something and assign that type to the val, then use B guessed to be A in map.

But with Seq(1,2,3).toSet.map it guesses that there is some B >: Int which it should then map into... what exactly? You can guess the type of _ * 2 only if you know the type of _.

Long story short that [B :> A] seem to be the issue since if we do this:

implicit class AsSetOps[F, A](val fa: scala.collection.SeqLike[A, F]) {
  def asSet: Set[A] = fa.toSet[A]
}
Seq(1,2,3).asSet.map(_ * 2)

it works.

I can only guess that it was some attempt to make toSet covariant which backfired.

like image 61
Mateusz Kubuszok Avatar answered Oct 04 '22 21:10

Mateusz Kubuszok