Scala Upper bound of option type does not understand

I read functional programming in Scala, and in chapter 04, the authors themselves implement the option. Now, when defining the getOrElse function, they use the upper bound to restrict type A supertype (if understood correctly)

So the definition is:

 sealed trait Option[+A] { def getOrElse[B >: A](default: => B): B = this match { case None => default case Some(a) => a } } 

So, when we have something like

 val a = Some(4) println(a.getOrElse(None)) => println prints a integer value val b = None println(b.getOrElse(Some(3)) => println prints a Option[Integer] value 

A is of type Option[Int] , so A will be of type Int . B will be of type Nothing . Nothing is a subtype of any other type. This means that Option[Nothing] is a subtype of Option[Int] (due to covariance), right?

But with B >: A we said that B must be a supertype ?! So how can we get Int back? It confuses me a little ...

Does anyone want to try and clarify?

+5
source share
1 answer

This means that Option [Nothing] is a subtype of the [Int] option (due to covariance), right?

Right. Option[Nothing] is Option[Int] .

But with B>: A, we said that B must be a supertype ?! So how can we get int back?

It should not be a supertype. This requires A as a lower bound. This means that you can pass Int to getOrElse if A is Int .

But this does not mean that you cannot pass instances of the subclass. For instance:

 class A class B extends A class C extends B scala> Option(new B) res196: Option[B] = Some( B@661f82ac ) scala> res196.getOrElse(new C) res197: B = B@661f82ac scala> res196.getOrElse(new A) res198: A = B@661f82ac scala> res196.getOrElse("...") res199: Object = B@661f82ac 

I can pass an instance of C , because C can be added to B I can also pass a type above the inheritance tree, and getOrElse will return that type. If I pass in a type that has nothing to do with the type contained in Option , then the type with the smallest upper bound will be inferred. In the above case, this is Any .


So why is there a lower bound at all? Why not:

 def getOrElse[B <: A](default: => B): B 

This will not work, because getOrElse must either return A , which is contained in Option , or, by default, B But if we return A and A not B , so the type binding is not valid. Maybe if getOrElse returned A :

 def getOrElse[B <: A](default: => B): A 

This will work (if it were really defined that way), but you would be limited by type constraints. Therefore, in the above example, you can only pass B or C to getOrElse on Option[B] . In any case, this is not the case as in the standard library.


The getOrElse standard library allows you to pass anything to it. Say you have Option[A] . If we pass a subtype A , it will be added to A If we pass A , this is obviously normal. And if we pass some other type, then the compiler displays the smallest upper bound between them. In all cases, a correspondence of type B >: A is satisfied B >: A

Because getOrElse allows you to transfer something, many find it very difficult. For example, you could:

 val number = "blah" // ... lots of code val result = Option(1).getOrElse(number) 

And it will compile. We will only have Option[Any] , which is likely to throw an error somewhere else along the line.

+8
source

All Articles