Skip to content

Instantly share code, notes, and snippets.

@LPTK
Created April 4, 2015 05:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LPTK/01a1f873eab83e45a5de to your computer and use it in GitHub Desktop.
Save LPTK/01a1f873eab83e45a5de to your computer and use it in GitHub Desktop.
DSL for generic pattern matching
object GenPattern extends App {
abstract class TypeBase(val name: String)
trait Type[+T] { val base: TypeBase; val params: Seq[Type[_]]; override def toString = s"${base.name}[${params mkString ","}]" }
type Rep[+T] = Node[T]
trait Node[+T] { val typ: Type[T]; val args: Seq[_] }
case class Comp[+T](typ: Type[T], args: Rep[_]*) extends Node[T]
{ override def toString = s"$typ(${args mkString ","})" }
case class Const[+T](typ: Type[T], v: T) extends Node[T] { val args = Seq(v) }
object Int extends TypeBase("Int") with Type[scala.Int] { val base = this; val params = List() }
implicit def int2Const(x: Int) = Const(Int, x)
object Vector extends TypeBase("Vector") {
def <[T] (t: Type[T]) = new { def > (xs: Rep[T]*) = Vector(t) of (xs: _*) }
}
case class Vector[+A](p: Type[A]) extends Type[Seq[A]] { val name = "Seq"; val base = Vector; val params = List(p) }
implicit class VectorOf[A](val self: Vector[A]) {
def of(xs: Rep[A]*) = Comp[Seq[A]](self, xs: _*)
}
object VectorOf {
def unapplySeq(n: Node[Seq[_]]) = n match { case Comp(typ,args@_*) => Some(Seq(typ.base) ++ args) }
}
object Hashmap extends TypeBase("Map")
case class Hashmap[A,+B](pa: Type[A], pb: Type[B]) extends Type[Map[A,B]] { val base = Hashmap; val params = List(pa,pb) }
implicit class HashmapOf[A,B](val self: Hashmap[A,B]) {
def of() = Comp[Map[A,B]](self)
}
object of {
def unapplySeq[T](n: Node[T]) = Some(Seq(n.typ) ++ n.args)
}
object ofSome {
def unapply[T](n: Node[T]) = Some(n.typ, n.args.size)
}
object < {
def unapplySeq[T](n: Node[T]) = Some(Seq(n.typ.base) ++ n.typ.params)
}
object > {
def unapplySeq[T](n: Node[T]) = Some(Seq(n) ++ n.args)
}
{
val v = Vector(Int) of (1,2,3)
val m = Hashmap(Int, Vector(Int)) of ()
Vector(Int) match {
case Vector(t) => println(s"Vector with type $t")
}
Vector(Vector(Int)) match {
case Vector(t) if false => // idea infers t: Type[Seq[Int]]
case Vector(Vector(t)) => Hashmap(Int,t)
}
Vector(Int) of (1,2,3) match {
case Vector(Int) of (Const(Int,1),Const(Int,2),Const(Int,3)) =>
}
Vector(Int) of (1,2,3) match { case Vector(_) of (x,y,z) => println(s"$x,$y,$z") }
Vector(Int) of (1,2,3) match { case VectorOf(args @ _*) => println(s"$args") }
Vector<Int>(1,2,3) match { case Vector<Int>(x,y,z) => println(s"$x,$y,$z") }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment