1
votes

I'm trying to create a trait that has a generic function that returns a slick Query and has a value of that function compiled, like this:

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

  val Asc = Compiled(asc _)
}

But when I try to compile I get this error:

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

because scala cannot infer the implicit parameter compilable: Compilable[V, C] of Compiled.apply

The problem is the type parameter A1, indeed this would compile without problems:

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

  val Asc = Compiled(asc _)
}

I'm using slick 3.2.3

How can I make scala infer the right implicit?

1
You need to make Asc a lazy val or there is a risk of using uninitialised data in that call to asc.Tim

1 Answers

2
votes

In order for the compiled macro to work properly, you need the implicit parameters for this macro in scope. Since traits do not accept implicit parameters, i make these traits abstract classes.

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

A slightly more simple option can be used if a1 is always a 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 _)
  }

Note: If you do not want to use abstract classes, you could define an implicit def as follows:

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

When implementing this trait you should be able to implement it as follows (if the type is known):

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