====== Lab 5. Functional vs Object-Oriented decomposition ======
==== 4.1. The type Nat =====
Consider the following type defined to represent natural numbers:
trait Nat {
def isZero: Boolean
def add(other: Nat): Nat
def subtract(other: Nat): Nat
def greater(other: Nat): Boolean
def toInt: Int
}
case object Zero extends Nat
case class Succ(n: Nat) extends Nat
When implementing the following methods, think about whether or not they are **local** (are they best implemented using functional or OO decomposition?)
**4.1.1.** Implement the method ''isZero'' which checks if a number is equal to ''Zero'' or not.
**4.1.2.** Implement the addition method over natural numbers.
**4.1.3.** Implement the subtraction method over natural numbers. If $math[n > m] then $math[m - n = 0].
**4.1.4.** Implement ''greater'' which checks if a natural number is strictly larger than the other.
**4.1.5.** Implement a function which converts a Nat to a Scala Int.
==== 4.2. The type OList (Object-Oriented implementation of lists) ====
Start with the following trait, which encodes lists over integers.
trait OList{
def head: Int
def tail: OList
def foldRight[B](acc: B)(op: (Int,B) => B): B
def foldLeft[B](acc: B)(op: (B,Int) => B): B
def indexOf(i: Int): Int
def filter(p: Int => Boolean): OList
def map(f: Int => Int): OList
def partition(p: Int => Boolean): (OList, OList)
def slice(start: Int, stop: Int): OList
def forall(p: Int => Boolean): Boolean
}
**4.2.1.** Implement the constructors for the **empty list** as well as for the **nonempty list of integers**.
**4.2.2.** Implement ''head'' and ''tail'' accordingly.
**4.2.3.** Implement ''foldRight''. Follow the same strategy as in the previous labs. Also implement foldLeft. Make sure it is tail-recursive.
**4.2.5.** Implement ''filter''. Try and use ''foldRight'' in your implementation. The following diagram illustrates the behaviour of ''filter'':
1 2 3 4 5 6 7 8 9 10 11
filter(p => p % 2 == 0)
2 4 6 8 10
**4.2.4.** Implement ''indexOf'' which retrieves the position of an element in a list if it exists and -1 otherwise. Try and use an appropriate type of fold for your implementation.
**4.2.6.** Implement ''map''. Try and use an appropriate type of fold in your implementation. The following diagram illustrates the behaviour of map:
1 2 3 4 5 6 7 8 9 10
map (_*2)
2 4 6 8 10 12 14 16 18 20
**4.2.7.** Implement ''partition''. It is supposed to return a pair of lists. (!!) Try and use an appropriate type of fold in your implementation. The following diagram illustrates the behaviour of partition:
1 2 3 4 5 6 7 8 9 10
partition(_ % 2 == 0)
(1 3 5 7 9, 2 4 6 8 10)
**4.2.8.** Implement ''slice''. The following diagram illustrates the behaviour of slice:
1 2 3 4 5 6 7 8 9 10
slice(2,4)
3 4 5
**4.2.8.** Implement ''forall''. Try and use an appropriate type of fold in your implementation. The following diagram illustrates the behaviour of forall:
1 2 3 4 5 6 7 8 9 10
forall(_ % 2 == 0)
false