Skip to content

Instantly share code, notes, and snippets.

@OlivierBlanvillain
Created October 28, 2016 20:37
Show Gist options
  • Save OlivierBlanvillain/0d3f629413b285d0ab94d0d26fe8bd7e to your computer and use it in GitHub Desktop.
Save OlivierBlanvillain/0d3f629413b285d0ab94d0d26fe8bd7e to your computer and use it in GitHub Desktop.
scalaVersion := "2.11.8"
scalaOrganization := "org.typelevel"
libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.2"
scalacOptions += "-Yliteral-types"
sbt.version=0.13.13-RC2
import shapeless._
import shapeless.ops.record.Selector
import scala.language.implicitConversions
/** Mock for `org.apache.spark.sql.Dataset` */
trait Dataset[T] {
def select[O](f: QuerySyntax[T] => Column[O]): Dataset[O] = ???
}
/** Mock for `org.apache.spark.sql.Column` */
trait Column[S] {
def add(other: Column[S]): Column[S] = ???
def /(other: Column[S]): Column[S] = ???
def widen[T](implicit e: CanWidden[S, T]): Column[T] = ???
}
/** Typeclass for explicit implicit numeric widening */
trait CanWidden[T, S]
object CanWidden {
implicit val intToDouble: CanWidden[Int, Double] = new CanWidden[Int, Double] {}
}
/** Pure syntactic construct to construct `Column` expressions */
trait QuerySyntax[T] {
def of[S <: Singleton, V](s: S)(implicit f: ExistsSingleton[T, S, V]): Column[V] =
new Column[V] {}
def of2[S, V](column: Witness.Aux[S])(implicit f: ExistsSymbol[T, S, V]): Column[V] =
new Column[V] {}
}
object Demo extends LiftString {
case class Foo(i: Int, j: Int, d: Double, a: java.util.Date)
val ds: Dataset[Foo] = null
// Explicit singleton syntax
ds.select { col =>
(col.of("i") add col.of("j")).widen[Double] / col.of("d")
}
// Implicit singleton syntax
ds.select { implicit col =>
("i" add "j").widen[Double] / "d"
}
// Explicit symbol syntax
ds.select { col =>
(col.of2('i) add col.of2('j)).widen[Double] / col.of2('d)
}
// Won't compile!
// Implicit symbol syntax
// ds.select { implicit col =>
// ('i add 'j).widen[Double] / 'd
// }
}
trait LiftString {
implicit def liftStringSingleton[S <: Singleton, T, V](s: S)
(implicit d: QuerySyntax[T], f: ExistsSingleton[T, S, V]): Column[V] =
new Column[V] {}
implicit def liftStringSymbol[S, T, V](column: Witness.Aux[S])
(implicit d: QuerySyntax[T], f: ExistsSymbol[T, S, V]): Column[V] =
new Column[V] {}
}
@annotation.implicitNotFound(msg = "No column ${K} of type ${V} in ${T} using Singleton")
trait ExistsSingleton[T, K, V]
object ExistsSingleton {
implicit def deriveSingleton[T, H <: HList, K, V]
(implicit
l: LabelledGeneric.Aux[T, H],
s: Selector.Aux[H, Symbol with shapeless.tag.Tagged[K], V]
): ExistsSingleton[T, K, V] =
new ExistsSingleton[T, K, V] {}
}
@annotation.implicitNotFound(msg = "No column ${K} of type ${V} in ${T} using Symbol")
trait ExistsSymbol[T, K, V]
object ExistsSymbol {
implicit def deriveSymbol[T, H <: HList, K, V]
(implicit
l: LabelledGeneric.Aux[T, H],
s: Selector.Aux[H, K, V]
): ExistsSymbol[T, K, V] =
new ExistsSymbol[T, K, V] {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment