scala/epOc1.scala

// Base data

// trait BaseD;
trait BaseOp[D, T] {def perform(data: D): T}
class NumD(val value: Int) {
    def operI(op: BaseOp[D, Int]) = op.perform(this)
    def operS(op: BaseOp[D, String]) = op.perform(this)
}
class Num0 {};
class NumD(val value: Int) extends Num0 with BaseD[Num0] {
}

object NumD {val n12 = new NumD(12)};

/* / Concrete data implementation.
class NumD(val value: Int) extends BaseD {
} */

// 1st concrete operation: evaluate the data
object evalOp extends BaseOp[NumD, Int] {
  def perform(data: NumD) = data.value
}

object eval {
    def apply(data: NumD) = evalOp.perform(data)
}
// extension: operation repr
object reprOp extends BaseOp[NumD, String] {
  def perform(data: NumD) = '<' + data.value.toString + '>'
}

/*
class PlusD

val b = new NumD(123)
b.operI(evalOp)
// utility object for on-the-fly evaluations
object eval {def apply(data: BaseD) = new EvalOp()(data)}
*/