Reputation: 2272
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
.
Upvotes: 2
Views: 68
Reputation: 2272
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.
Upvotes: 0