This is an old revision of the document!


Lab 3. Algebraic Datatype Definition

Below, you will find the algebraic definition of the datatype IList:

Void : IList
Cons : Int x IList -> IList

This definition has already been implemented in Scala, as shown below. Please copy-paste this definition in your worksheet.

trait IList 
case object Void extends IList
case class Cons(x: Int, xs: IList) extends IList

3.1.1. Consider the following axioms for the operator isEmpty.

isEmpty : IList -> Boolean
isEmpty(Void) = true
isEmpty(Cons(h,t)) = false.

Implement isEmpty in Scala:

! Hint: To pattern match the list l as a Void or a Cons use the keyword match from Scala :

def isEmpty(l: IList) : Boolean = {
    l match {
        case Void => ???
        case Cons(x, xs) => ???
    }
}

3.1.2. Write down axioms for size : IList → Int and implement the operator in Scala:

def size(l: IList) : Int = ???

3.1.3. Implement contains to check if an element is a member of a list.

def contains(e: Int, l: IList) : Boolean = ???

3.1.4. Implement max which returns the largest integer from a list:

def max(l: IList) : Int = ???

3.1.5. Implement take which returns a new list containing the first n elements of the original list:

def take(n: Int)(l: IList) : IList = ???

3.1.6. Implement drop which returns a new list containing the original list without the first n elements:

def drop(n: Int)(l: IList) : IList = ???

3.1.7. Implement append which concatenates two lists:

def append(l1: IList, l2: IList) : IList = ???

3.1.8. (!) Implement last which returns the last element from a list:

def last(l: IList) : Int = ???

3.1.9. (!) Implement reverse. There are two different ways to implement reverse (with direct and with tail-end recursion). Try both implementations.

def reverse(l: IList) : IList = ???

3.1.10. Implement isSorted which checks if a list is sorted:

def isSorted(l: IList) : Boolean = ???

3.1.11. Implement merge which merges two sorted lists:

def merge(l1: IList, l2: IList) : IList = ???

3.1.12. Implement mergeSort which sorts a list:

def mergesort(l: IList) : IList = ???

The type definition for Scala is given below. Please copy-paste this definition in your worksheet.

trait BinaryTree {
    override def toString: String = super.toString: String
}
 
case object TVoid extends BinaryTree {
    override def toString: String = "-"
}
 
case class Node(left: BinaryTree, info: Int, right: BinaryTree) extends BinaryTree {
    override def toString: String = {
        def prettyPrint(tree: BinaryTree, depth: Int): String = {
            tree match {
                case TVoid =>"\t" * (depth + 1) +  tree.toString() + "\n"
                case Node(l, value, r) =>
                    "\t" * (depth + 1) + value.toString() + "\n" +
                    prettyPrint(l, depth+1) + prettyPrint(r, depth+1)
            }
        }
 
        prettyPrint(this, 0)
    }
}

A Binary Tree can either be a TVoid object (equivalent to NULL in C), or a Node with its information as an Int and two other trees as children (left and right).

3.2.0. Implement leaf_node that receives an Int and returns a leaf with that integer as the node's value:

def leaf_node(value : Int) : BinaryTree = ???

Being given the following BinaryTree:

val arborica = Node(Node(leaf_node(-1), 5, TVoid), 1, Node(leaf_node(4), 2, Node(leaf_node(3), 6, leaf_node(7))))

Implement the following methods for trees in Scala:

3.2.1. Implement mirror that mirrors the tree structure:

def mirror(tree: BinaryTree) : BinaryTree = ???

3.2.1. Implement flatten that squashes the tree traversed in preorder into a list: def flatten(tree: BinaryTree): List[Int] = ???

– 7. Define list concatenation over type List a: app :: (List a) → (List a) → (List a) app GVoid GVoid = GVoid app l1 GVoid = l1 app GVoid l2 = l2 app (GenCel val pointer) l2 = GenCel val (app pointer l2)

– 8. Define the function tmap which is the Tree a correspondent to map::(a→b) → [a] → [b]. tmap:: (a→b) → (Tree a) → (Tree b) tmap f TVoid = TVoid tmap f (Node l k r) = Node (tmap f l) (f k) (tmap f r)

– 10. Define the function tfoldr: tfoldr :: (a → b → b) → b → Tree a → b tfoldr f acc TVoid = acc tfoldr f acc (Node l k r) = tfoldr f (tfoldr f (f k acc) l) r

– 11. Implement the flattening function using tfoldr: flattening :: Tree a → List a flattening (Node l k r) = tfoldr GenCel GVoid (Node l k r)