-
Notifications
You must be signed in to change notification settings - Fork 72
Introduce typeclasses making it easier to write generic extension methods #478
Conversation
array.intersperse(0) | ||
array.view.intersperse(0) | ||
string.intersperse(' ') | ||
string.view.intersperse(' ') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This approach works with List
, Vector
but also views, Array
and String
.
However, there seems to be some type information lost somewhere:
val result = list.intersperse(0)
result: List[Int]
[error] found : Any
[error] required: strawman.collection.immutable.List[Int]
[error] result: List[Int]
[error] ^
6dc1511
to
718bcb9
Compare
Here is a design that make it possible to define a decorator that will work for any collection-like type, whether it is a collection (e.g.
implicit class SeqDecorator[C, S <: HasSeqOps[C]](coll: C)(implicit val seq: S) { … } (note that if scala/scala3#3964 or scala/bug#5712 were solved we could just write the following: The definition of trait HasSeqOps[C] {
type A
def apply(c: C): SeqOps[A, _, _]
} The type def intersperse[B >: seq.A](sep: B) = …
def intersperse[B >: seq.A, That](sep: B)(implicit bf: BuildFrom[C, B, That]): That =
bf.fromSpecificIterable(coll)(new View.Intersperse(seq(coll), sep)) The drawbacks of this design are:
|
5e3ddde
to
4256142
Compare
trait HasImmutableMapOps[C] extends HasMapOps[C] { | ||
|
||
// Convenient intermediate type definitions to satisfy type bounds | ||
protected type _CC[X, +Y] <: immutable.MapOps[X, Y, _CC, _] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the user ever needs to interact with this type directly, I would change the name to something more memorable, e.g. MapOf
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an implementation detail which is not supposed to be used by users. I wish I could get rid of it but couldn’t figure out how.
|
||
// Convenient intermediate type definitions to satisfy type bounds | ||
protected type _CC[X, +Y] <: immutable.MapOps[X, Y, _CC, _] | ||
protected type _C <: immutable.MapOps[K, V, _CC, _C] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, if the user needs to interact with this it should have a better name, e.g. MapType
.
protected type _C <: immutable.MapOps[K, V, _CC, _C] | ||
|
||
/** A conversion from the type `C` to `immutable.MapOps[K, V, _, _]` */ | ||
val conversion: C => immutable.MapOps[K, V, _CC, _C] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this a val? I would think this would be easiest to use as a def apply, so you can (implicit ops: M)
and then in the code ops(coll)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. This is fixed.
The strategy looks sound overall, though I do worry that the complexity will seem daunting to people even if mostly it "just works". We'll need some good documentation. Also, I think we could improve the usability a bit (as indicated on my comments for |
In any case, this framework mainly targets advanced users. A first support of generic decorators is already provided by If one needs more power (ie the ability to also abstract over views, Last, I’ve put this machinery in the |
HasSeqOps is a type class whose instances let users retrieve the associated collection type and collection type constructor of any type that can be seen as a sequence.
86b32ae
to
f487dc2
Compare
Rebased |
@szeiger any objection to merge this one? |
Fixes #294.