Skip to content

Instantly share code, notes, and snippets.

@IainHull
Last active June 1, 2018 14: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 IainHull/e2a280ef871a3ac4484f68505d38c6a9 to your computer and use it in GitHub Desktop.
Save IainHull/e2a280ef871a3ac4484f68505d38c6a9 to your computer and use it in GitHub Desktop.
import $ivy.`com.chuusai::shapeless:2.3.3`
import shapeless._
import shapeless.poly._
import shapeless.ops.hlist._
import shapeless.UnaryTCConstraint._
trait ColumnType[T] {
type ScalaType = T
type JavaType
def toJava(v: ScalaType): JavaType
}
object ColumnType {
implicit object StringType extends ColumnType[String] {
type JavaType = String
def toJava(v: String) = v
}
implicit object IntType extends ColumnType[Int] {
type JavaType = java.lang.Integer
def toJava(v: Int) = new java.lang.Integer(v)
}
}
case class Column[T : ColumnType](name: String, desc: String)
object abstractColumnToScalaType extends Poly1 {
implicit def default[T](implicit ev: ColumnType[T]) = at[Column[T]](v => null.asInstanceOf[ev.ScalaType])
}
object scalaTypeToJavaTypes extends Poly1 {
implicit def default[T](implicit ev: ColumnType[T]) = at[T](v => ev.toJava(v))
}
// *->*[Column]#λ uses UnaryTCConstraint to ensure that every element of L is a Column[T]
class Logger[L <: HList : *->*[Column]#λ](val columns: L) {
type ColumnTypes = L
// the evedence that UnaryTCConstraint is applied has gone now
// so we do not know that every element of L is a Column[T] :-(
// Once we have an instance of Logger and the compiler has resolved ColumnTypes
// The Mapper below works
// The Mapped type gives us what we want but goes in the wrong direction :-(
//val scalaMapper = Mapper[abstractColumnToScalaType.type, ColumnTypes]
//type ScalaValues = scalaMapper.Out
// val javaMapper = Mapper[scalaTypeToJavaTypes.type, ScalaValues]
// type JavaValues = javaMapper.Out
// def apply[P <: Product, M <: HList](p: P)(
// implicit
// gen: Generic.Aux[P, ScalaValues],
// mapper: Mapper.Aux[scalaTypeToJavaTypes.type, L, M]
// ) = gen.to(p).map(scalaTypeToJavaTypes)
}
import ColumnType._
val str = Column[String]("string", "")
val int = Column[Int]("int", "")
val logger = new Logger(str :: int :: HNil)
val scalaMapper = Mapper[abstractColumnToScalaType.type, logger.ColumnTypes]
class Logger2[L <: HList](val columns: L)(implicit scalaMapper: Mapper[abstractColumnToScalaType.type, L]) {
type ColumnTypes = L
type ScalaValues = scalaMapper.Out
}
// If this does not work next I would try an explicit TypeClass for HLists of Columns along the lines of
// https://stackoverflow.com/questions/49258650/shapeless-hlist-with-classtags
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment