Lecture 4. Algebraic datatypes in Scala

/*
Scala este orientat obiect - totul este un obiect
Stilul functional de a reprezenta date
 
 
Definitia TDA-ului:
 
Void : List
Cons : E x List -> List
 
 */
 
trait IList //trait este ca interface (din Java)
case object Void extends IList
case class Cons(x: Int, xs: IList) extends IList
 
/*
  Diferentele intre "case class" si "class" in Scala:
   1. un case class, are un SINGUR constructor
   2. parametrii constructorului unui case class sunt IMUTABILI
   3. un obiect construit cu un case class este IMUTABIL
   4. egalitatea intre obiecte este STRUCTURALA
      doua obiecte sunt egale daca sunt construite la fel
 
 */
// pattern matching - foarte des folosita in limbajele functionale
/*
   Definition and axioms:
   size: List -> Int
   size(Void) = 1
   size(Cons(x,xs)) = 1 + size(xs)
 */
def size(l: IList): Int =
  l match {
    case Void => 0
    case Cons(_,xs) => 1 + size(xs)
  }
/* Definition and axioms:
   append: List x List -> List
   append(Void,l) = l
   append(Cons(x,xs),l)) = Cons(x,append(xs,l))
 */
def append(l1: IList, l2: IList): IList =
  l1 match {
    case Void => l2
    case Cons(x,xs) => Cons(x,append(xs,l2))
  }
 
append(Cons(1,Cons(2,Void)),Cons(3,Void))
/*
   Definition and axioms:
   reverse: List -> List
   reverse(Void) = Void
   reverse(Cons(x,xs)) = append(reverse(xs),Cons(x,Void))
 */
def reverse(l: IList): IList =
  l match {
    case Void => Void
    case Cons(x,xs) => append(reverse(xs),Cons(x,Void))
  }
reverse(Cons(1,Cons(2,Cons(3,Void))))
 
/*
   Definition and axioms:
   last: List -> Int
   last (Cons(x,Void)) = x
   last (Cons(x,Cons(y,ys))) = last(Cons(y,ys))
 */
def last(l: IList): Int =
  l match {
    case Cons(x,Void) => x
    case Cons(_,Cons(y,ys)) => last(Cons(y,ys))
  }