scala - 将 Slick 与无形的 HList 一起使用

标签 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
}

最佳答案

你一针见血——如果你能生产ShapesHLists ,Slick 的其余机器将启动以生产 ProvenShape您需要默认投影。

这是一个准系统实现,允许您创建 TablesHLists :

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)
}

我已经在 Github 上实现了 here .原则上我认为Generic可以在不需要 <> 的情况下参与到映射案例类的战斗中.

关于scala - 将 Slick 与无形的 HList 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31764514/

相关文章:

scala - 生成类型类实例时无法证明单例类型是单例类型

scala - 带有内部案例类的案例类的字符串列表

scala - 缺少大小.unapply

scala - 在带有 DI 的 Play 2.4 中,如何在 "Secured"特征中使用服务类?

swing - Scala中的惯用表格单元渲染器

Scala - 避免过于复杂的嵌套模式匹配

scala 光滑的 postgresql 创建表模式

scala - 空列表平等如何工作?

scala - Akka 2.1 最小远程 actor 示例

scala - 为什么即使用于 sum 的列是强制列,slick 中的分组方法 sum 也会返回 Option?