Last active
June 1, 2018 14:53
-
-
Save IainHull/e2a280ef871a3ac4484f68505d38c6a9 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 $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