2
votes

There are countless questions on this topic and a quite good, if not very precisely worded article here: Revisiting implicits without the import tax. I've read most of them, but have a problem with overriding default CanBuildFrom implicits without repeating the declarations myself. If you're familiar with scala collection library and resolution of CanBuildFrom, you know that for every scala collection trait CC[X], its companion object defines an implicit CanBuildFrom[CC[_], X, CC[X]] instance. I have introduced my own collection hierarchy, rooted in a class derived from IndexedSeq[X]:

trait SpecSeq[X] extends IndexedSeq[X]
trait MutableSeq[X] extends SpecSeq[X]
trait ConstSeq[X] extends SpecSeq[X]
trait ArraySeq[X] extends MutableSeq[X]
trait ConstArray[X] extends ConstSeq[X]

Can I avoid declaring implicit values in companion objects of all defined traits and instead extract them to a common base trait for the companion objects? I tried having:

trait SpecCompanion[S[X]<:SpecSeq[X]] {
    implicit def canBuildFrom[X] :CanBuildFrom[S[_], X, S[X]] = ???
}
ArraySeq extends SpecCompanion[ArraySeq]
ConstArray extends SpecCompanion[ConstArray]
...

Unfortunately, those definitions aren't considered more specific than the one declared in object IndexedSeq. This issue is aggreviated by the fact that in reality it's not a single implicit value, but several with increasing level of requirements for X.

1

1 Answers

0
votes

I ended up with a layer of indirection and my own sublass of CanBuildFrom:

trait SpecCanBuildFrom[-F, -E, +T] extends CanBuildFrom[F, E, T]

trait SpecCompanion[S[X]<:SpecSeqw[X]] {
    implicit def cbf[X] :SpecCanBuildFrom[S[_], X, S[S]] = ???
}

object SpecSeq extends SpecCompanion[SpecSeq] {
    implicit def canBuildFrom[C[X]<:SpecSeq[X], X](implicit ev :SpecCanBuildFrom[C[_], X, C[X]) :CanBuildFrom[C[_], X, C[X]] = ev
}

object ArraySeq extends SpecCompanion[ArraySeq]
object ConstArray extends SpecCompanion[ConstArray]

Now the generic definition in SpecSeq overrides all implicits in scala collections.

Good enough, but I wonder if it is possible to do it directly.