This is an old revision of the document!


Lab 06. Polymorphism in Scala

This lab will start with the implementations discussed during lecture. Please find the polymorphic trait FList[A] below:

trait FList[A]{ // list with elements of type A
  def length: Int
  def head: A
  def tail: FList[A]
  def map[B](f: A => B): FList[B]
  // a op (b op (c op acc))
  def foldRight[B](acc: B)(op: (A,B) => B): B
  // ((acc op a) op b) op c
  def foldLeft[B](acc: B)(op: (B,A) => B): B
 
  def contains(e: A):Boolean =
    this.foldRight(false)(_ == e || _)
 
}

together with the implementations:

case class FNil[A]() extends FList[A]{
  override def length: Int = 0
  override def head: A = throw new Exception("head on empty list")
  override def tail: FList[A] = throw new Exception("head on empty list")
  override def map[B](f: A => B): FList[B] = FNil[B]
  override def foldRight[B](acc: B)(op: (A,B) => B): B = acc
  override def foldLeft[B](acc: B)(op: (B,A) => B): B = acc
}
 
case class Cons[A](x:A, xs:FList[A]) extends FList[A]{
  override def length = 1 + xs.length
  override def head:A = x
  override def tail:FList[A] = xs
  override def map[B](f: A => B): FList[B] =
    Cons(f(x),xs.map(f))
  override def foldRight[B](acc: B)(op: (A,B) => B): B =
    op(x, xs.foldRight(acc)(op))
  override def foldLeft[B](acc: B)(op: (B,A) => B): B =
    xs.foldLeft(op(acc,x))(op)
  }
}

Add the following methods in the trait FList and implement them. Some methods can be directly implemented in the trait, using map, foldRight, foldLeft or other functions.

  • Can you figure which ones are best implemented in the trait and which in the case classes?

6.1. indexOf determines the position of a value in the list (starting with 0)

def indexOf(e: A): Int