Documentation: improve typeclasses tutorial
I am just reading typeclasses.html intro text, and am getting confused by the very first code sample: def combineAll[A](list: List[A], A: Monoid[A]): A = list.foldRight(A.empty)(A.combine) - I mean, is there a reason to name both parameter of A and the type parameter [A] just the same?
Wouldn't it make more sense when written as a: Monoid[A] or just monoid: Monoid[A]. I don't understand what is the intent when having one "shadow" the other.
And then I can't make any sense of the next proposition: def combineAll[A <: Monoid[A]](list: List[A]): A = ??? at all - so you declare function combineAll that will take only list of A, but the elements must be a subtype of Monoid[A]. What? It's nonsense, you could not even sum up Ints like that, so it must be clearly marked as such: a fruitless hypothetical.
Why would anyone want to sum up a list of Monoid[Int] items, and what outcome it might have? Clearly you can't add two Monoid instances together! Now, because the text is referring to getting the "empty value" by calling "empty" method on Monoid[A] instance, etc etc - I understand it's a hypothetical, but it's just so remarkably confusing!
Codecov Report
Merging #2133 into master will not change coverage. The diff coverage is
n/a.
@@ Coverage Diff @@
## master #2133 +/- ##
=======================================
Coverage 94.66% 94.66%
=======================================
Files 328 328
Lines 5533 5533
Branches 199 199
=======================================
Hits 5238 5238
Misses 295 295
Continue to review full report at Codecov.
Legend - Click here to learn more
Δ = absolute <relative> (impact),ø = not affected,? = missing dataPowered by Codecov. Last update 4298e17...97759ee. Read the comment docs.
Why would anyone want to sum up a list of Monoid[Int] items, and what outcome it might have?
Think of that same way as about creating a java TreeSet from a collection of elements, they all have to extend/implement Comparable. So called subtyping approach.
in that case you would have something like
trait Monoid[A] {
self: A =>
def empty: A
def combine(another: A): A
}
class Int extends Monoid[Int] {
def empty: Int = 0
def combine(another: Int): Int = this + another
}
the confusing part here as that we usually don't even think of things like Ints to implement any interfaces (though java.lang.Integer implements Comparable). As we usually(never?) control those types.
Hi @jozic, I would like to incorporate this into article, because it seriously tripped me up. Thanks!
The tutorial first talks about Int and intAdditionMonoid and then suddenly jumps to A <: Monoid[A] which makes no sense if you don't have the appropriate context.
I wish it will gently introduce going from the first Int monoid to a complex A type which mixes in a Monoid trait instead. Then discussion of A <: Monoid[A] signature starts making sense.