Defining an algebraic data type
In order to support variable rates, we need to change the signature of all functions that accept interestRate: Double. Instead of a double, we need a type that can represent either a constant rate or a sequence of rates.
Considering two types A and B, we previously saw how to define a type that can hold a value of type A and a value of type B. This is a product type, and we can define it using a tuple, such as ab: (A, B), or a case class, such as case class MyProduct(a: A, b: B).
On the other hand, a type that can hold either A or B is a sum type, and in Scala, we declare it using a sealed trait inheritance:
sealed trait Shape
case class Circle(diameter: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape
An Algebraic Data Type (ADT) is a type that composes sum types and product types to define a data structure. In the preceding code, we defined a Shape ADT, which composes a sum type (a Shape can be a Circle or a Rectangle), with a product type Rectangle (a Rectangle holds a width and a height).
The sealed keyword indicates that all subclasses of the trait must be declared in the same .scala file. If you attempt to declare a class that extends a sealed trait in another file, the compiler will reject it. This is used to guarantee that our inheritance tree is complete, and as we will see later on, it has interesting benefits when it comes to using pattern matching.
Going back to our problem, we can define a Returns ADT as follows. Create a new Scala class in the retcalc package in src/main/scala:
package retcalc
sealed trait Returns
case class FixedReturns(annualRate: Double) extends Returns
case class VariableReturns(returns: Vector[VariableReturn]) extends Returns
case class VariableReturn(monthId: String, monthlyRate: Double)
For VariableReturn, we keep the monthly interest rate and an identifier monthId that will have the form 2017.02, for February 2017. I recommend that you use Vector whenever you need to model a sequence of elements. Vector is faster than List for appending/inserting elements or accessing an element by index.