Scala Doobie фрагмент с параметром универсального типа

Я пытаюсь абстрагироваться от вставки объектов разных типов в таблицы SQL аналогичной структуры. Вот что я пытаюсь сделать:

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

Но я получаю эту ошибку компиляции:

[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(_ => ())

Все, что я могу найти в документации:

Doobie позволяет интерполировать значения любого типа (и их параметры) с экземпляром Meta, который включает в себя...

Но, похоже, этого недостаточно; какой тип / класс импорта / преобразования мне нужен?

2 ответа

Я отвечу на свой вопрос почти год спустя. Я никогда полностью не понимал, что происходит, и с тех пор обновился до более новой версии doobie, поэтому я не уверен, насколько это актуально. Но теперь в документации есть подсказка:

Примечание: важно понимать, что Meta существует только для того, чтобы вводить пары Get/Put в неявную область видимости. Вы никогда не должны требовать Meta как свидетельство в коде пользователя: вместо этого требуйте Get, Put или и то, и другое.

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

И действительно, между этим изменением и новой версией теперь это прекрасно для меня компилируется:

class TableAccess[A: Get: Put](table: String) {

Один из способов, который я решил, это локализовать параметры типа (и их доказательства) в методе (на статическом / сопутствующем объекте), а затем он скомпилирован.

Что-то вроде

object MinimalGood {
  def good[A: Meta, B: Meta](a: A, b: B): Update0 =
  sql"""$a $b""".update
}

Когда компилятор разрешает неявно, он ищет один из определенного типа в текущей области видимости. Здесь кажется, что он нашел больше, чем один в своем поиске дерева.

Дело не в отсутствующем классе типов или импорте, скорее, их слишком много, и компилятор не может подобрать правильный. Попробуйте удалить некоторые неявные и посмотреть, как это работает или передать их явно.

Другие вопросы по тегам