package scala.examples.tcpoly.dgp.gm.light trait Either[a,b] case class Inl[a,b](el: a) extends Either[a,b] case class Inr[a,b](el: b) extends Either[a,b] trait GenericCore { trait GenFun[Result] { // cases for fixed set of types: def unit: Unit => Result def char: Char => Result def int: Int => Result def either[a <% Rep[a], b <% Rep[b]]: Either[a, b] => Result def both[a <% Rep[a], b <% Rep[b]] : Pair[a, b] => Result def apply[t <% Rep[t]](x: t): Result = x.rep(this)(x) def datatype[a <% Rep[a], b](iso: Iso[a,b]): b => Result = (x: b) => this(iso.fromData(x)) } case class Iso[t,dt](fromData: dt=>t, toData: t=>dt) trait Rep[t]{ def rep[R](implicit gen: GenFun[R]): t => R } } trait CoreConvs requires (GenericCore with CoreConvs) { implicit def unit2rep(u: Unit) = new Rep[Unit] { def rep[R](implicit gen: GenFun[R]): Unit => R = gen.unit } implicit def int2rep(i: Int): Rep[Int] = new Rep[Int] { def rep[R](implicit gen: GenFun[R]): Int => R = gen.int } implicit def char2rep(c: Char): Rep[Char] = new Rep[Char] { def rep[R](implicit gen: GenFun[R]): Char => R = gen.char } implicit def pair2rep[t <% Rep[t], u <% Rep[u]](p: Pair[t, u]): Rep[Pair[t, u]] = new Rep[Pair[t, u]]{def rep[R](implicit gen: GenFun[R]): Pair[t, u] => R = gen.both } implicit def plus2rep[t <% Rep[t], u <% Rep[u]](p: Either[t, u]): Rep[Either[t, u]] = new Rep[Either[t, u]]{def rep[R](implicit gen: GenFun[R]): Either[t, u] => R = gen.either } implicit def list2rep[t <% Rep[t]](l: List[t]): Rep[List[t]] = { def fromList[t](l: List[t]): Either[Unit, Pair[t, List[t]]] = l match { case Nil => Inl(()) case x :: xs => Inr(Pair(x, xs)) } def toList[t](l: Either[Unit, Pair[t, List[t]]]): List[t] = l match { case Inl(())=> Nil case Inr(Pair(x, xs)) => x :: xs } new Rep[List[t]]{def rep[R](implicit gen: GenFun[R]): List[t] => R = gen.datatype(Iso(fromList[t], toList[t])) } } } trait GenericShowBin requires (GenericCore with CoreConvs with GenericShowBin) { object showBin extends GenFun[List[Bit]] { def unit = ((x: Unit) => Nil) def either[a <% Rep[a], b <% Rep[b]] = (x: Either[a, b]) => x match { case Inl(el) => _0 :: this(el) case Inr(el) => _1 :: this(el) } def both[a <% Rep[a], b <% Rep[b]] = (x: Pair[a, b]) => this(x._1) ::: this(x._2) def char = (x: Char) => bits(16,x) def int = (x: Int) => bits(32,x) } sealed trait Bit case object _0 extends Bit case object _1 extends Bit def bits(n: Int, x: Int): List[Bit] = if(n==0) Nil else {if((x&1)==1) _1 else _0} :: bits(n-1,x>>1) } object Test extends GenericCore with CoreConvs with GenericShowBin with Application { Console.println(showBin(List(1,2,3))) }