Элементы HList для соответствия типу типа параметров класса - PullRequest
0 голосов
/ 06 июня 2018

Я пытаюсь реализовать нечто похожее на определения таблиц и столбцов в 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.

...