【发布时间】:2019-10-17 09:56:39
【问题描述】:
我目前遇到一个问题,我正在尝试使用隐式类重载 quill 中包含的方法,通常这在简单的情况下是可能的,即如果你有类似的东西
class Test {
def rawr(string: String): String = string
}
您可以使用不同的类型轻松重载rawr 的定义
implicit final class RawrExt(val t: Test) {
def rawr(int: Int): Int = int
}
这会按预期编译,即
val t = new Test
t.rawr(5)
即使Test 有更复杂的类型参数,这仍然有效,即
class Test[T <: Number] {
def rawr(string: String): String = string
}
implicit final class RawrExt[N <: Number](val t: Test[N]) {
def rawr(int: Int): Int = int
}
val t = new Test[BigDecimal]
t.rawr(5)
当我尝试为 quill-monix-jdbc 的事务实现完全相同的重载时,我遇到了问题。使用 monix-quill-jdbc 时,您有一个具有以下签名的事务方法
def transaction[A](f: Task[A]): Task[A]
问题是我们在应用程序逻辑中使用了TaskResult,即Either 和Task 使用猫的Monad Transformer,即
type TaskResult[T] = EitherT[Task, GeneralError, T]
我想要做的是为transaction 提供覆盖,它采用TaskResult 而不是Task,在implicit class 中定义它非常简单
object TaskResultSupport {
implicit final class TaskResultCtxSupport[Dialect <: SqlIdiom, Naming <: NamingStrategy](
val value: MonixJdbcContext[Dialect, Naming]) {
def transaction[A](f: TaskResult[A]): TaskResult[A] =
EitherT(value.transaction(f.value))
}
}
然后当我们尝试使用它时,我们得到一个编译错误,它似乎无法获取implicit class。
val ctx: PostgresMonixJdbcContext[SnakeCase] =
new PostgresMonixJdbcContext(SnakeCase, "database")
val taskResult: TaskResult[Unit] = TaskResult(())
ctx.transaction(taskResult) // This doesn't compile
我尝试了定义隐式类的所有各种排列,即作为示例
implicit final class TaskResultCtxSupport(val value: MonixJdbcContext[_, _]) extends AnyVal
似乎没有一个有效。这是编译错误
type mismatch;
found : Playground.this.Implicits.TaskResult[Unit]
(which expands to) cats.data.EitherT[monix.eval.Task,Playground.this.GeneralError,Unit]
required: monix.eval.Task[?]
可以在https://scastie.scala-lang.org/pqAn8fUPTbmBqToCVIXDXA 找到演示问题的 scastie。感谢 Martjin Hoekstra,这里有一个进一步最小化的示例https://scastie.scala-lang.org/4YrhP0HSRzu7F9numrqAGQ。 Scala 贡献者线程可以在这里找到https://contributors.scala-lang.org/t/scala-compiler-unable-to-overload-methods-with-type-parameters/3761
【问题讨论】:
-
编译错误是什么?
-
它在 scastie 中,但我会编辑帖子以使其更清晰。
标签: scala overloading implicit quill