2
votes

I am looking at scala in action book and it has this code

sealed abstract class Maybe[+A] {
    def isEmpty: Boolean
    def get: A
    def getOrElse[B >: A](default: B): B = {
        if(isEmpty) default else get
    }
}
    final case class Just[A](value: A) extends Maybe[A] {
    def isEmpty = false
    def get = value
}
case object Nil extends Maybe[scala.Nothing] {
    def isEmpty = true
    def get = throw new NoSuchElementException("Nil.get")
}

If the signature of getOrElse is defined as def getOrElse(default: A): A = It doesnt compile.

The author states "The lower bound B >: A declares that the type parameter B is constrained to some super type of type A"

Yet I seem to be able to do this and it works

val j1 = Just(1)                                  
val l1 = j1.getOrElse("fdsf")  //l1  : Any = 1

Is String a super type of Int? What am i not understanding as to why this works? Its like its falling back to argument 1 being type A being of type Any (which it is) rather than type Int.

1

1 Answers

3
votes

In Scala you cannot have covariant types in method parameters.

This is because allowing covariant types in method parameters breaks type safety.

In order to have a covariant type you must use a bounded type:

getOrElse[B >: A](default: B): B

This says find some type, B, such that it is a superclass of A and that becomes the method return type.

In your case A is Int and you pass in a String. The only type B which is a superclass of both Int and String is Any.

In this case B becomes Any so the method returns Any.