Edit this page Backlinks This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ====== Lab 3. Algebraic Datatype Definition ====== ===== 3.1 Abstract Lists ===== Below, you will find the algebraic definition of the datatype ''IList'': <code> Void : IList Cons : Int x IList -> IList </code> This definition has already been implemented in Scala, as shown below. Please copy-paste this definition in your worksheet. <code scala> trait IList case object Void extends IList case class Cons(x: Int, xs: IList) extends IList </code> **3.1.1.** Consider the following axioms for the operator ''isEmpty''. <code> isEmpty : IList -> Boolean isEmpty(Void) = true isEmpty(Cons(h,t)) = false. </code> Implement ''isEmpty'' in Scala: ''! Hint:'' To pattern match the list l as a Void or a Cons use the keyword ''match'' from Scala : <code scala> def isEmpty(l: IList) : Boolean = { l match { case Void => ??? case Cons(x, xs) => ??? } } </code> **3.1.2.** Write down axioms for ''size : IList -> Int'' and implement the operator in Scala: <code scala> def size(l: IList) : Int = ??? </code> **3.1.3.** Implement ''contains'' to check if an element is a member of a list. <code scala> def contains(e: Int, l: IList) : Boolean = ??? </code> **3.1.4.** Implement ''max'' which returns the largest integer from a list: <code scala> def max(l: IList) : Int = ??? </code> **3.1.5.** Implement ''take'' which returns a new list containing the first ''n'' elements of the original list: <code scala> def take(n: Int)(l: IList) : IList = ??? </code> **3.1.6.** Implement ''drop'' which returns a new list containing the original list without the first ''n'' elements: <code scala> def drop(n: Int)(l: IList) : IList = ??? </code> **3.1.7.** Implement ''append'' which concatenates two lists: <code scala> def append(l1: IList, l2: IList) : IList = ??? </code> **3.1.8.** (!) Implement ''last'' which returns the last element from a list: <code scala> def last(l: IList) : Int = ??? </code> **3.1.9.** (!) Implement ''reverse''. There are two different ways to implement reverse (with direct and with tail-end recursion). Try both implementations. <code scala> def reverse(l: IList) : IList = ??? </code> **3.1.10.** Implement ''isSorted'' which checks if a list is sorted: <code scala> def isSorted(l: IList) : Boolean = ??? </code> **3.1.11.** Implement ''merge'' which merges two sorted lists: <code scala> def merge(l1: IList, l2: IList) : IList = ??? </code> **3.1.12.** Implement ''mergeSort'' which sorts a list: <code scala> def mergesort(l: IList) : IList = ??? </code> ===== 3.2 Binary Tree ===== The binary tree type definition for Scala is given below. Please copy-paste this definition in your Main.scala file from your laboratory project, in order for printTree to work properly. Call print from the function main and click the "run" text above the definition of main to see the result in terminal. <code scala> 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 printTree( tree: BinaryTree, prefix: String = "", isLeft: Boolean = true ): String = tree match { case TVoid => "" case Node(l, value, r) => val rightStr = printTree(r, prefix + (if (isLeft && prefix.nonEmpty) "│ " else " "), isLeft = false) val nodeStr = prefix + (if (tree != this) if (isLeft) "└── " else "┌── " else " ") + value.toString + "\n" val leftStr = printTree(l, prefix + (if (isLeft) " " else "│ ")) rightStr + nodeStr + leftStr } '\n' + printTree(this) } } </code> 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: <code scala> def leaf_node(value : Int) : BinaryTree = ??? </code> Being given the following BinaryTree: <code scala> val arborica = Node(Node(leaf_node(-1), 5, TVoid), 1, Node(leaf_node(4), 2, Node(leaf_node(3), 6, leaf_node(7)))) </code> Implement the following methods for trees in Scala: **3.2.1.** Implement ''mirror'' that mirrors the tree structure: <code scala> def mirror(tree: BinaryTree) : BinaryTree = ??? </code> **3.2.1.** Implement ''flatten'' that squashes the tree traversed in preorder into a list: <code scala> def flatten(tree: BinaryTree): List[Int] = ??? </code> **3.2.2.** Define the function ''tmap'' which is the Tree a correspondent to map::(a→b) → [a] → [b]. <code scala> def tmap(f: Int => Int, tree: BinaryTree) : BinaryTree = ??? </code> **3.2.3.** ! Define the function ''tfoldr'', equivalent of foldr for trees: foldr :: (a -> b -> b) -> b -> Tree a -> b <code scala> def tfoldr[B](f: (Int, B) => B, acc: B, tree: BinaryTree): B = ??? </code> **3.2.4.** ! Implement the ''flattening'' function using tfoldr. The order of squashing the tree does not necessarily need to match the previous exercise: <code scala> def flattening(tree: BinaryTree): List[Int] = ??? </code>