Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala doobie fragment with generic type parameter

Tags:

sql

scala

doobie

I am trying to abstract inserting objects of different types into sql tables of similar structure. Here's what I'm trying to do:

class TableAccess[A : Meta](table: String) {
  def insert(key: String, a: A): ConnectionIO[Unit] = {
    (fr"insert into " ++ Fragment.const(table) ++ fr" values ($key, $a);").update.run.map(_ => ())
  }
}

But I get this compile error:

[error] diverging implicit expansion for type doobie.util.param.Param[A]
[error] starting with method fromMeta in object Param
[error]     (fr"insert into " ++ Fragment.const(table) ++ fr" values ($key, $a);").update.run.map(_ => ())

All I can find in the documentation is:

doobie allows you to interpolate values of any type (and options thereof) with an Meta instance, which includes...

But it seems that is not enough in this case; what's the right typeclass/imports/conversions I need?

like image 675
Joe K Avatar asked Feb 17 '18 02:02

Joe K


1 Answers

I'll go ahead an answer my own question, almost a year later. I never fully understood what was happening, and I have since updated to a newer version of doobie, so I am not sure how relevant this is. But now the documentation contains this clue:

Note: it is important to understand that Meta exists only to introduce Get/Put pairs into implicit scope. You should never demand Meta as evidence in user code: instead demand Get, Put, or both.

def foo[A: Meta](...)     // don't do this
def foo[A: Get: Put](...) // ok

And indeed, between that change and the new version, this now compiles just fine for me:

class TableAccess[A: Get: Put](table: String) {
like image 60
Joe K Avatar answered Sep 23 '22 18:09

Joe K