Curs 04. Tipuri de date functionale in Scala

/*
 
class Point (val x: Int, val y: Int) {
 
  def higher(p: Point): Boolean = p.x > this.x
 
  // string interpolation
  override def toString: String = s"(${x},${y})"
}
 
new Point(1,2)
val p = new Point(1,2)
p.x
 
new Point(1,2) == new Point(1,2)
 */
 
trait Nat  // pt moment, acelasi lucru cu interface
 
case object Zero extends Nat
case class Succ(next: Nat) extends Nat
 
Succ(Succ(Succ(Zero)))
Succ(Zero) == Succ(Zero)
 
def add(n: Nat, m: Nat): Nat =
  n match {
    case Zero => m
    case Succ(np) => Succ(add(np,m))
  }
add(Succ(Zero),Succ(Zero))
 
def equals(n: Nat, m: Nat): Boolean =
  (n,m) match {
    case (Zero,Zero) => true
    case (Succ(x),Succ(y)) => equals(x,y)
    case _ => false
  }
 
trait IList {
  // this.append(other)
  def append(other: IList): IList
  def size(): Int
  def take(n: Int): IList
  def drop(n: Int): IList
  def merge(other: IList): IList
  def mergesort(): IList
}
 
case object Void extends IList {
  override def size(): Int = 0
  override def append(l: IList):IList = l
  override def take(n: Int): IList = Void
  override def drop(n: Int): IList = Void
  override def merge(other: IList): IList = other
  override def mergesort(): IList = ???
}
case class Cons(h: Int, t: IList) extends IList {
  override def size(): Int = 1 + t.size()
  override def append(l: IList): IList = Cons(h,t.append(l))
  override def take(n: Int): IList =
    if (n == 0) Void
    else Cons(h,t.take(n-1))
 
  override def drop(n: Int): IList =
    if (n == 0) this
    else t.drop(n-1)
 
  // h and t... comparata cu "other"
  override def merge(other: IList): IList =
    other match {
      case Void => ???
      case Cons(x,xs) => ???
    }
  /*
    Daca avem de implementat o operatie locala, o putem face
    cu usurinta intr-un membu de clasa.
 
    Daca avem nevoie de informatii din afara clasei, e de preferat
    abordarea folosind pattern matching.
 
    (append este LOCAL pt ca nu imi pasa de cealalta lista)
   */
 
  override def mergesort(): IList = ???
}
// alta abordare
def merge(l1: IList, l2: IList): IList =
  (l1,l2) match {
    case (Void,_) => l2
    case (_,Void) => l1
    case (Cons(x,xs), Cons(y,ys)) =>
      if (x > y) Cons(y,merge(l1,ys))
      else Cons(x,merge(xs,l2))
  }