Search code examples
scalaslicktyping

Attempting to figure out the correct type for this


Apologies, this is going to be a somewhat noob-ish question. I have an object from the slick library that has at type like this:

Query[(Rep[String], Rep[String]), (String, String), Seq]

I'm trying to write a function which accepts queries as arguments, though the sequences in them are of uncertain length - ie, it could equally well be:

Query[(Rep[String], Rep[String], Rep[String]), (String, String, String), Seq]

So the first two components have three elements rather than two. I cannot figure out how this is done. I have tried various erroneous permutations, like Query[Product[Rep[String]], Product[String], Seq], to no avail, and even what I assumed would be the nuclear option of just using Any doesn't work. My error messages are along the lines of

[error]  found   : Option[slick.driver.H2Driver.api.Query[(slick.driver.H2Driver.api.Rep[String], slick.driver.H2Driver.api.Rep[String]),(String, St
ring),Seq]]
[error]     (which expands to)  Option[slick.lifted.Query[(slick.lifted.Rep[String], slick.lifted.Rep[String]),(String, String),Seq]]
[error]  required: Option[slick.driver.H2Driver.api.Rep[scala.concurrent.Future[List[String]]]]
[error]     (which expands to)  Option[slick.lifted.Rep[scala.concurrent.Future[List[String]]]]
[error]       ReturnFunctions.completeQuery(db, query, serialize_and_send)

I think my inability to solve this may reflect some fundamental lack of understanding about scala, strongly typed languages in general and possibly also computing as a whole. Should I be resolving this Query to some more definite form before I try to even pass it into a function? I also suspect I'm not interpreting the original type correctly - what do the parantheses mean in this context? Is it that Query is expecting to receive three sets of parameters, one after the other, like when you do fn(arg1)(arg2)(arg3) = ...?

Any help with this troubling dilemma gratefully received.


Solution

  • I also suspect I'm not interpreting the original type correctly - what do the parentheses mean in this context?

    You're looked at a reasonable advanced area, but let's try to help.

    The Query type always has three type parameters. You'll see them written as Query[M, U, C].

    The first parameter, M, is a tuple. That's what the parentheses mean in this context.

    In your first example, M is a tuple of two elements; and in the second it's three. The same situation exists for the second parameter, U. There's a bit more detail on this in Essential Slick.

    In Scala, you can have generic parameters. That means you can say something along the lines of:

    def foo[M, U, C[_]](q: Query[M,U,C]) = ???
    

    We've defined a method with:

    • three type parameters; and
    • taking an argument of a query that has those types.

    We've not said anything about M, U, or much about C (other than that it's a type that takes a type as an argument). That means there's not a lot we can do with them, but you may not need to.

    A post on query enrichment in Slick gives a longer (related) example which may be of use.

    As Dmytro suggests, a better route would be to create a concrete example of what you'd like to achieve and work from there.