Я пытаюсь реализовать нечто похожее на определения таблиц и столбцов в Slick, используя Shapeless.
Этот код будет работать со сторонней библиотекой Java, поэтому в какой-то момент мне нужно преобразовать HList вArray[Any]
.
Несмотря на то, что то, что следует, похоже, работает, это не выглядит правильным способом:
import shapeless._
import ops.hlist._
trait ColumnType[A]
object ColumnType {
implicit object StringType extends ColumnType[String]
implicit object IntType extends ColumnType[Int]
implicit object BooleanType extends ColumnType[Boolean]
}
case class Column[T : ColumnType](name: String, description: String)
trait Logger[L <: HList] {
val columns: L
object javaTypes extends Poly1 {
implicit def caseInt = at[Int](i => new java.lang.Integer(i))
implicit def caseString = at[String](identity)
implicit def caseBoolean = at[Boolean](b => new java.lang.Boolean(b))
}
object extract extends Poly1 {
implicit def caseT[T : ColumnType] = at[Column[T]](_.asInstanceOf[T])
}
def apply[P <: Product, M <: HList](p: P)(
implicit
gen: Generic.Aux[P, L],
mapper: Mapper.Aux[javaTypes.type, L, M]
): List[Any] = gen.to(p).map(javaTypes).runtimeList
}
A Logger
будет определенонапример:
class AccessLog extends Logger[String :: Int :: Boolean :: HNil] {
val path = Column[String]("path", "uri path")
val statusCode = Column[Int]("statusCode", "status code")
val authenticated = Column[Boolean]("authenticated", "is user authenticated")
val columns = HList(path, statusCode, authenticated).map(extract)
}
И будет использоваться:
val accessLog = new AccessLog
accessLog("1", 2, false).foreach(p => println(s"$p: ${p.getClass}"))
Требования состоят в том, чтобы тип columns
соответствовал параметру типа регистратора, а также способу преобразованияпередаваемые значения в типы Java.
Мне особенно непонятно, как определяется extract
.