Why is f-bounded polymorphism im Scala commonly implemented with an upper type bound as well as a self type

96 Views Asked by At

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.

1

There are 1 best solutions below

17
On BEST ANSWER

So, the idea of trait MyTrait[A <: MyTrait[A]] { self: A => ... } is to force A 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.

   trait Foo[A] { self: A => }
   trait Bar 
   class Baz extends Foo[Bar] with Bar

Or even just class Bat extends Foo[Any]