【问题标题】:Scala doobie fragment with generic type parameter具有泛型类型参数的 Scala doobie 片段
【发布时间】:2020-01-07 03:10:29
【问题描述】:

我正在尝试将不同类型的对象抽象插入到类似结构的 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 实例,其中包括...

但在这种情况下似乎还不够;我需要什么正确的 typeclass/imports/conversions?

【问题讨论】:

标签: sql scala doobie


【解决方案1】:

大约一年后,我会继续回答我自己的问题。我从来没有完全理解发生了什么,而且我已经更新到更新版本的 doobie,所以我不确定这有多相关。但是现在文档中包含了这个线索:

注意:重要的是要理解 Meta 的存在只是为了引入 获取/将对放入隐式范围。你永远不应该要求 Meta 作为 用户代码中的证据:改为要求 Get、Put 或两者兼而有之。

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

确实,在更改和新版本之间,现在编译对我来说很好:

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

【讨论】:

    【解决方案2】:

    当编译器解析隐式时,它会在当前范围内搜索特定类型之一。在这里,他似乎在树搜索中发现了不止一个。

    这不是缺少类型类或导入的问题,更像是你有太多的类型而编译器无法找到正确的类型。 尝试删除一些隐式并查看其工作原理或显式传递它们。

    【讨论】:

      【解决方案3】:

      我解决此问题的一种方法是将类型参数(及其证据)本地化到方法上(在静态/伴随对象上),然后编译。

      类似

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-09
        • 2020-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-23
        • 1970-01-01
        相关资源
        最近更新 更多