consider a simple function that operates on collections distinctBy
, which, like distinct
remove "duplicates" (which are not necessary actual duplicates):
import scala.collection.TraversableLike
import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.{Set=>MSet}
def distinctBy[T,R,Coll]
(xs: Coll)
(f: T => R)
(implicit ev: Coll <:< TraversableLike[T,Coll],
cbf: CanBuildFrom[Coll,T,Coll]): Coll = {
val builder = cbf(xs)
builder.sizeHint(xs.size)
val seen = MSet.empty[R]
xs.foreach { elem =>
if(!seen(f(elem))){
builder += elem
}
}
builder.result()
}
now consider a class to use it on:
case class X(i: Int, j: Int)
using this function naively fails:
scala> distinctBy(Vector(X(1,2),X(3,2),X(1,1),X(2,2)))(_.i)
<console>:14: error: missing parameter type for expanded function ((x$1) => x$1.i)
distinctBy(Vector(X(1,2),X(3,2),X(1,1),X(2,2)))(_.i)
^
<console>:14: error: Cannot construct a collection of type scala.collection.immutable.Vector[X] with elements of type Any based on a collection of type scala.collection.immutable.Vector[X].
distinctBy(Vector(X(1,2),X(3,2),X(1,1),X(2,2)))(_.i)
^
but if I help the type inferencer, this works:
scala> distinctBy(Vector(X(1,2),X(3,2),X(1,1),X(2,2)))((x:X) => x.i)
res1: scala.collection.immutable.Vector[X] = Vector(X(1,2), X(3,2), X(1,1), X(2,2))
scala> distinctBy[X,Int,Vector[X]](Vector(X(1,2),X(3,2),X(1,1),X(2,2)))(_.i)
res2: scala.collection.immutable.Vector[X] = Vector(X(1,2), X(3,2), X(1,1), X(2,2))
to my best understanding, since the function is given in a second argument list, the type inferencer should have picked up that it's a function from X
to something. and since X
has a member i
of type Int
, all should have been OK with the first try. so, what am I missing here?