使用Slick和无形HList

时间:2015-08-01 17:49:04

标签: scala slick shapeless hlist

Slick HList的支持通常是一件好事。不幸的是,它带有自己的实现,几乎不提供任何有用的操作。因此,我喜欢使用无形 HList。这应该是" trivial",但我不知道如何做到这一点。在网上搜索我发现没有证据表明有人设法完成了这项任务。

我认为它足以实现ProvenShape(如宣传的here),但因为我无法理解 Slick的概念 (Proven)Shape s,我没有管理这个。

我基本上是为了煮这个

class   Users( tag: Tag )
extends Table[Long :: String :: HNil]( tag, "users" )
{
    def id = column[Long]( "id", O.PrimaryKey, O.AutoInc )

    def email = column[String]( "email" )

    override def * = ( id, email ) <>[TableElementType, ( Long, String )](
        _.productElements,
        hlist => Some( hlist.tupled )
    )
}

class   Users( tag: Tag )
extends Table[Long :: String :: HNil]( tag, "users" )
{
    def id = column[Long]( "id", O.PrimaryKey, O.AutoInc )

    def email = column[String]( "email" )

    override def * = id :: email :: HNil
}

1 个答案:

答案 0 :(得分:8)

你击中了头上的钉子 - 如果你可以为ProvenShape生成Tables,其余的Slick机器将开始生产你需要的HLists用于默认投影。

这是一个简单的实现,可让您创建import scala.annotation.tailrec import scala.reflect.ClassTag import shapeless.{ HList, ::, HNil } import slick.lifted.{ Shape, ShapeLevel, MappedProductShape } final class HListShape[L <: ShapeLevel, M <: HList, U <: HList : ClassTag, P <: HList] (val shapes: Seq[Shape[_, _, _, _]]) extends MappedProductShape[L, HList, M, U, P] { def buildValue(elems: IndexedSeq[Any]) = elems.foldRight(HNil: HList)(_ :: _) def copy(shapes: Seq[Shape[_ <: ShapeLevel, _, _, _]]) = new HListShape(shapes) def classTag: ClassTag[U] = implicitly def runtimeList(value: HList): List[Any] = { @tailrec def loop(value: HList, acc: List[Any] = Nil): List[Any] = value match { case HNil => acc case hd :: tl => loop(tl, hd :: acc) } loop(value).reverse } override def getIterator(value: HList): Iterator[Any] = runtimeList(value).iterator def getElement(value: HList, idx: Int): Any = runtimeList(value)(idx) } object HListShape { implicit def hnilShape[L <: ShapeLevel]: HListShape[L, HNil, HNil, HNil] = new HListShape[L, HNil, HNil, HNil](Nil) implicit def hconsShape[L <: ShapeLevel, M1, M2 <: HList, U1, U2 <: HList, P1, P2 <: HList] (implicit s1: Shape[_ <: ShapeLevel, M1, U1, P1], s2: HListShape[_ <: ShapeLevel, M2, U2, P2]): HListShape[L, M1 :: M2, U1 :: U2, P1 :: P2] = new HListShape[L, M1 :: M2, U1 :: U2, P1 :: P2](s1 +: s2.shapes) } Generic

<>

我已经在Github here上实施了一个实现。原则上我认为可以将php带入战斗以映射案例类而无需{{1}}。