Why is f-bounded polymorphism in Scala commonly implemented with an upper type bound as well as a self type like
trait MyTrait[A <: MyTrait[A]] { self: A =>
…
}
and not simply with just a self type like
trait MyTrait[A] { self: A =>
…
}
The upper type bound in the first example seems to be unnecessary. At least I can't find any benefits of using one. Am I overlooking something here? The type bounds does however stand in the way of usages like
def func[A](implicit ev: A <:< MyTrait[A]) = ???
(of course in this simplistic and contrived example a func[A <: MyTrait[A]]
would resolve the issue but that might not be possible in a more complex setting)
I found f-bounded polymorphism implemented with a type bound in multiple libraries and even in an introductory blog post about the topic (https://tpolecat.github.io/2015/04/29/f-bounds.html) and was wondering if it would be better to omit the type bound in general.
So, the idea of
trait MyTrait[A <: MyTrait[A]] { self: A => ... }
is to forceA
to be the type of the current implementation.If you omit the upper bound, then, aside from
Foo
not being able to do very much with its type parameter (it knows nothing about its members), you can also do things like this, which is not very useful.Or even just
class Bat extends Foo[Any]