This is an old revision of the document!
Lab 08: Polymorphism
8.1. Ad-hoc polymorphism
Consider the following implementation of the type Nat, which you are well-familiar with:
trait Nat { def +(other: Nat): Nat } case object Zero extends Nat{ override def +(other: Nat): Nat = other } case class Succ(n: Nat) extends Nat{ override def +(other: Nat): Nat = Succ(n + other) }
It might be the case that we would like to use nat values from different sources, e.g. fromInteger(1) + Zero + fromString(“2”). Keeping track of all different functions that convert other values to Nat might be tedious. A work-around is to:  (1) define a companion object for Nat by creating a new object with the same name as Nat, in the same scala file (or worksheet).
object Nat { // a companion object for trait Nat }
We can now populate the companion objects with any methods we would like. In particular, we can add a method:
def apply(i: Int): Nat = ???
which can be called simply as: Nat(5). Also, we can  (2) overload apply in order to support creating naturals with the call Nat(.) from different other types.
8.1. Create a companion object for Nat and add appropriate apply functions in order to make the expression Nat(1) + Zero + Nat(“2”) successfully compile and run.