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 not?