-
Notifications
You must be signed in to change notification settings - Fork 320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add blogpost: Tribulations of CanBuildFrom #651
Conversation
Perhaps I'm being picky, but why use "Kind polymorphism" as the heading of a section which doesn't further discuss kind polymorphism (either as implemented in Typelevel Scala or elsewhere) and which illustrates without comment exactly the sort of arity-specific boilerplate which kind polymorphism in some form could eliminate? |
@milessabin Actually I think “Kind polymorphism” is probably not an appropriate heading. Also, unfortunately, in practice the way kind-polymorphism is implemented in Typelevel Scala does not really make things simpler: trait MapDef[A, B, CC <: AnyKind] {
type In
type Out
def map(in: In)(f: A => B): Out
}
trait IterableOps[A, CC <: AnyKind] {
def map[B](f: A => B)(implicit mapDef: MapDef[A, B, CC] { type In = this.type }): mapDef.Out = mapDef.map(this)(f)
}
trait Map[K, V] { … }
object Map {
implicit def mapDef[K, V, L, W]: MapDef[(K, V), (L, W), Map] { type In = Map[K, V]; type Out = Map[L, W] } = …
} |
@julienrf I think changing the heading is the best bet. Yes, the minimal kind polymorphism in TLS isn't up to this job, but I think it's worth exploring what can be done with something quite that minimal, and I think it would be worth exploring more sophisticated implementations. |
|
||
The drawback of this solution is that the type signature of the `map` method looks cryptic. | ||
|
||
In the new design we solve this problem by defining two overloads of the `map` |
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.
You may want to point out that this new design required improvements to type inference which are only available in 2.12.
get a `Seq[B]`. | ||
|
||
Thus, we got rid of the cryptic method signatures while still supporting the feature | ||
of returning a different type of result according to the type of the transformation function. |
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.
but we lose the ability to abstract over arbitrary map
implementations in a unified way
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 think this point is not very important from the point of view of users. That’s more related to our internal implementation.
You may also want to mention |
About |
I disagree. |
OK, I added a section about |
~~~ | ||
|
||
`breakOut` selects a `CanBuildFrom` instance irrespective of the initial collection type. | ||
In our case the `Map[Int, Int]` type annotation fixes the target type of the builder |
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.
How about "This requires the target type to be known, in this case via an explicit type ascription"?
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.
LGTM :) Merci @julienrf and thank you @milessabin and @szeiger for your reviews! :)
The plan is to publish the blogpost next Monday.