Lab 4. 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 $ n > m$ then $ 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