scala/ScalaBook/chapter-03/genStack4.scala

abstract class Stack{
  type Q
  def push(x: Q):Stack
  def pop:Stack
  def top:Q
}

case object EmptyStack extends Stack {
  def push(x: Any) = new StackC(x,this)
  def pop:Stack = 
    throw new NoSuchElementException("stack underflow")
  def top : Any = 
    throw new NoSuchElementException("top of empty stack") 
}

case class StackC(e: Q, s: Stack) extends Stack {
  type Q
  def this(e : Q) = this(e, EmptyStack.asInstanceOf[Stack])
  def push (x : Q) = new StackC(x, this)
  def pop = s
  def top = e.asInstanceOf[Q] 
}

Stack {type Q = Int }
StacjC {type Q = Int }
val q0 = new StackC(5)
val q1 = StackC(3,StackC(4,q0))
println(q1)
val q2 = q1.pop
println(q2)
val q3 = q2.pop
println(q3)
val q4 = q3.push(9)
println(q4)
var x = 7 + q4.top
println("x = " + x)
Stack {type Q = String }
StacjC {type Q = String }
val s1 = new StackC[String]("a")
val s2 = s1.push("b")
println(s2)