Created
October 28, 2016 20:37
-
-
Save OlivierBlanvillain/0d3f629413b285d0ab94d0d26fe8bd7e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
scalaVersion := "2.11.8" | |
scalaOrganization := "org.typelevel" | |
libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.2" | |
scalacOptions += "-Yliteral-types" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sbt.version=0.13.13-RC2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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