0

In Scala's upper bound concept, the given type or its super type can be passed. For example, in the below method S is the type and A is the parameter we pass. This method accepts all the values present in Scala's type system actually. S, S subtype and its super type. This is due to the fact that all types extends Any type.

def method[A >: S](a:A) = { ... }

Then why can't we write all the upper bound notations as Any (which is the universal type in Scala). The above definition can be re-written as:

def met(a:Any) = { ... }

This is easy to understand.

What sort of advantage the upperbound brings in ?

Thanks!

user3103957
  • 636
  • 4
  • 16
  • 1
    is the operator in question not the lower bound operator? :https://docs.scala-lang.org/tour/lower-type-bounds.html – Taus Aug 06 '21 at 11:26

1 Answers1

3

It allows you to lose less type information than you would by going to Any.

For example If you have Dog and Cat inherit Animal, this works:

val maybeDog: Option[Dog] = ???

val pet = maybeDog.getOrElse(Cat())

Because getOrElse has a signature of def getOrElse[B >: A](default: => B): B, it is inferred that B is Animal (as the least upper bound of Cat and Dog), so the static type of val pet is Animal. If it was using Any, the result would require unsafe casting to work further. If it was not introducing a new type parameter altogether, you would be forced to write (maybeDog: Option[Animal]).getOrElse(Cat()) to achieve the same unification.


Additionally, it restricts the implementation to not do something completely silly. For example, this typechecks:

def getOrElse[A](option: Option[A])(default: => Any): Any = 42 // Int is Any, so why not?

While this doesn't:

def getOrElse[A, B >: A](option: Option[A])(default: => B): B = 42 

Because while anything can go as B, that doesn't imply that Int is always a subtype of B.

Oleg Pyzhcov
  • 7,323
  • 1
  • 18
  • 30
  • Thanks Oleg, for your nice answer. In the second definition of getOrElse, whatever type 'B' belongs to, since it is used as upper bound, is 42 not ok? not sure why it errors out. Because whatever type (since it extends Any) we use, it would be satisfied for the upper bound check. – user3103957 Mar 29 '21 at 15:03
  • 1
    `B` extends `Any`, but you need to return specifically `B`, not `Any`. The parameter on method means "I work for all possible supertypes of A", whichever of them the _caller_ would want, not writer - that includes `A` itself, `Any`, and everything in-between. – Oleg Pyzhcov Mar 29 '21 at 15:33
  • Thanks again Oleg. It is clear now. I would like to enhance my knowledge on generics and advanced concepts in Scala further. Which book/material you would recommend. Thanks! – user3103957 Mar 30 '21 at 02:46
  • 1
    Honestly, my approach is to just write code and run into problems. Can't really suggest any books there. You can try Programming in Scala by Odersky et al. as a reference book, it has many topics, but for me it's no substitute for experience. You may also try working with/contributing to some FP library like cats and ask questions on gitter :D – Oleg Pyzhcov Mar 30 '21 at 06:00