scala/ScalaBook/chapter-03/numerals.scala

trait Nat
case object Zero extends Nat {
  override def toString = "Zero"
}
case class S(n:Nat) extends Nat 

var x = S(S(S(S(Zero))))
println(x)



def add(x:Nat, y:Nat):Nat =
  x match {
    case Zero => y
    case   _  => y match {
                   case Zero => x
                   case S(a) => add(S(x),a)
                 }
  }

var w1=S(S(S(Zero)))
var w2=S(S(S(S(Zero))))
println(add(w1,w2))

def foldN[α](z : α)(s: α => α)(n: Nat): α =
  n match {
    case Zero => z
    case S(a) => s(foldN(z)(s)(a))
  }

def succ(n: Nat) = S(n)
def add2(n: Nat, m: Nat): Nat = foldN[Nat](n)(succ)(m)
println(add2(w1,w2))