具有编译查询的光滑通用特征

Slick, generic trait with Compiled query

我正在尝试创建一个具有通用函数的特征,该函数 returns 一个巧妙的 Query 并且具有编译该函数的值,如下所示:

trait fn1[A1, E, U, C[_]] {
  protected def asc(a1: A1): Query[E, U, C]

  val Asc = Compiled(asc _)
}

但是当我尝试编译时出现这个错误:

Computation of type A1 => test.this.profile.api.Query[E,U,C] cannot be compiled (as type C)
val Asc = Compiled(asc _)

因为scala无法推断Compiled.apply

的隐式参数compilable: Compilable[V, C]

问题是类型参数 A1,实际上这会编译没有问题:

trait fn1[E, U, C[_]] {
  protected def asc(a1: Rep[Long]): Query[E, U, C]

  val Asc = Compiled(asc _)
}

我正在使用 slick 3.2.3

如何让 Scala 推断正确的隐式?

为了使编译后的宏正常工作,您需要在作用域中为该宏提供隐式参数。由于特征不接受隐式参数,我将这些特征抽象化 类.

  abstract class Fn1[A, P, E, U, C[_]](implicit ashape: Shape[ColumnsShapeLevel, A, P, A], pshape: Shape[ColumnsShapeLevel, P, P, _]) {
    protected def asc(a1: A): Query[E, U, C]
    lazy val Asc = Compiled(asc _)
  }

如果 a1 始终是 Rep[P]

,则可以使用稍微更简单的选项
  abstract class Fn2[P, E, U, C[_]](implicit btt: slick.ast.BaseTypedType[P]) {
    protected def asc(a1: Rep[P]): Query[E, U, C]
    lazy val Asc = Compiled(asc _)
  }

注意:如果你不想使用抽象类,你可以定义一个隐式定义如下:

trait Fn3[P, E, U, C[_]] {
  implicit def baseTypedTypeP: slick.ast.BaseTypedType[P]
  protected def asc(a1: Rep[P]): Query[E, U, C]
  lazy val Asc = Compiled(asc _)
}

当实现这个特性时,你应该能够按如下方式实现它(如果类型已知):

implicit def baseTypedTypeP: slick.ast.BaseTypedType[Long] = implicitly