Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| fp2023:lab05 [2023/03/21 17:45] pdmatei created | fp2023:lab05 [2023/03/31 12:58] (current) pdmatei | ||
|---|---|---|---|
| Line 4: | Line 4: | ||
| Consider the following type defined to represent natural numbers: | Consider the following type defined to represent natural numbers: | ||
| <code scala> | <code scala> | ||
| - | trait Nat | + | 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 object Zero extends Nat | ||
| case class Succ(n: Nat) extends Nat | case class Succ(n: Nat) extends Nat | ||
| </code> | </code> | ||
| - | **4.1.1.** Implement the following function: | + | When implementing the following methods, think about whether or not they are **local** (are they best implemented using functional or OO decomposition?) | 
| - | <code scala> | + | |
| - | def isZero(n: Nat): Nat = | + | |
| - | n match { | + | |
| - | case Zero => ??? | + | |
| - | case Succ(np) => ??? | + | |
| - | } | + | |
| - | </code> | + | |
| - | **4.1.2.** Implement the addition function over natural numbers: | + | **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. | ||
| <code scala> | <code scala> | ||
| - | def add(n: Nat, m: Nat): Nat = | + | trait OList{ | 
| - | n match { | + | def head: Int | 
| - | case Zero => ??? | + | def tail: OList | 
| - | case Succ(np) => ??? | + | 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 | ||
| + | } | ||
| </code> | </code> | ||
| - | **4.1.3.** Implement the subtraction function over natural numbers. If $math[n > m] then $math[m - n = 0]. | + | **4.2.1.** Implement the constructors for the **empty list** as well as for the **nonempty list of integers**. | 
| - | <code scala> | + | |
| - | def subtract(n: Nat, m: Nat): Nat = ??? | + | **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'': | ||
| + | <code> | ||
| + | 1 2 3 4 5 6 7 8 9 10 11 | ||
| + | filter(p => p % 2 == 0) | ||
| + | 2  4  6  8  10  | ||
| </code> | </code> | ||
| - | **4.1.4.** Implement ''greater'' which checks if a natural number is strictly larger than the other: | + | **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. | 
| - | <code scala> | + | |
| - | def greater(n: Nat, m: Nat): Nat = | + | |
| - | (n,m) match { | + | **4.2.6.** Implement ''map''. Try and use an appropriate type of fold in your implementation. The following diagram illustrates the behaviour of map: | 
| - | ??? | + | <code> | 
| - | } | + | 1 2 3 4 5 6 7 8 9 10 | 
| + | map (_*2) | ||
| + | 2 4 6 8 10 12 14 16 18 20 | ||
| </code> | </code> | ||
| - | **4.1.5.** Equality is already defined for all case classes, as structural equality (objects built in the same way are equal). However, re-implement equality over naturals: | + | **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: | 
| - | <code scala> | + | <code> | 
| - | def equal(n: Nat, m: Nat): Nat = ??? | + | 1 2 3 4 5 6 7 8 9 10 | 
| + | partition(_ % 2 == 0) | ||
| + | (1 3 5 7 9, 2 4 6 8 10) | ||
| </code> | </code> | ||
| - | **4.1.6.** Implement a function which converts a Nat to a Scala Int: | + | **4.2.8.** Implement ''slice''. The following diagram illustrates the behaviour of slice: | 
| - | <code scala> | + | <code> | 
| - | def toInt(n: Nat): Int = ??? | + | 1 2 3 4 5 6 7 8 9 10 | 
| + | slice(2,4) | ||
| + | 3 4 5 | ||
| </code> | </code> | ||
| - | **4.1.7.** Implement a function which converts an Int to a Nat: | + | **4.2.8.** Implement ''forall''. Try and use an appropriate type of fold in your implementation. The following diagram illustrates the behaviour of forall: | 
| - | <code scala> | + | <code> | 
| - | def fromInt(i: Int): Nat = ??? | + | 1 2 3 4 5 6 7 8 9 10 | 
| + | forall(_ % 2 == 0) | ||
| + | false | ||
| </code> | </code> | ||