Scala Lower Bounds
A lower bound is a limit on a type parameter that says how low a type may go. It requires every type used to be that type or a type above it.
Adding a dog keeps a dog kennel
The kennel starts with one dog. Adding a second dog keeps the kennel a kennel of dogs.
class Animal(val name: String)
class Dog(name: String) extends Animal(name)
class Cat(name: String) extends Animal(name)
class Kennel[A](val members: List[A]):
def add[B >: A](newcomer: B): Kennel[B] = Kennel(newcomer :: members)
@main def main(): Unit =
val dogs = Kennel(List(Dog("Rex")))
val more = dogs.add(Dog("Max"))
println(more.members.map(_.name))Adding an animal widens the kennel
The kennel starts with one dog. Adding an animal widens it to a kennel of animals.
class Animal(val name: String)
class Dog(name: String) extends Animal(name)
class Cat(name: String) extends Animal(name)
class Kennel[A](val members: List[A]):
def add[B >: A](newcomer: B): Kennel[B] = Kennel(newcomer :: members)
@main def main(): Unit =
val dogs = Kennel(List(Dog("Rex")))
val mixed = dogs.add(Animal("Sam"))
println(mixed.members.map(_.name))
println(mixed.members.length)A lower bound accepts both a dog and an animal
withRex takes a value of Dog or above. It builds a list of two in both calls.
class Animal(val name: String)
class Dog(name: String) extends Animal(name)
class Cat(name: String) extends Animal(name)
def withRex[T >: Dog](other: T): List[T] = List(Dog("Rex"), other)
@main def main(): Unit =
println(withRex(Dog("Max")).length)
println(withRex(Animal("Sam")).length)Example
class Animal(val name: String)
class Dog(name: String) extends Animal(name)
class Cat(name: String) extends Animal(name)
class Kennel[A](val members: List[A]):
def add[B >: A](newcomer: B): Kennel[B] = Kennel(newcomer :: members)
@main def main(): Unit =
val dogs = Kennel(List(Dog("Rex")))
val withDog = dogs.add(Dog("Max"))
val mixed = withDog.add(Animal("Sam"))
println(withDog.members.map(_.name))
println(mixed.members.map(_.name))
println(mixed.members.length)Key points
- Bound syntax: T >: Dog means T is Dog or a type above Dog, such as Animal.
- Accepting supertypes: a method with this bound can accept an Animal value as well as a Dog value.
- Widening containers: adding an Animal to a kennel of dogs widens the kennel to a kennel of animals.
- Method arguments: a lower bound is often used when a method takes in a value.
In this example, the kennel starts with one dog, adding a dog keeps two dogs in order with the newest first, and adding an animal widens the kennel to three animals.
Note
a lower bound is a floor, so Cat does not satisfy T >: Dog because Cat is not Dog and not above Dog.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Scastie
Exercise
What does T >: Dog allow?