当调用者具有参数化值时找不到类型类隐式

Typeclass implicit not found when caller has parametrized value

编辑:我删除了过于复杂的示例,该示例仅混淆了一个简单示例的问题

我正在尝试弄清楚如何使用方法为类型类提供必要的证据,其中一个参数是通用的,但应该可以从上下文中确定

trait Converter[A, B] {
  def apply(a: A, b: B): String
}

object Converters {

  implicit object DoubleIntConverter extends Converter[Double, Int] {
    override def apply(a: Double, b: Int): String = a.toString + ":" + b.toString
  }

  implicit object IntIntConverter extends Converter[Int, Int] {
    override def apply(a: Int, b: Int): String = a.toString + ":" + b.toString
  }

}

// passing in an Int
println(fun1(1))

// calling fun2 with Int and Int
def fun1[A](a: A) = fun2(a, 42)

def fun2[A, B](a: A, b: B)(implicit converter: Converter[A, B]): String = converter(a, b)

我得到的错误是:

Error:(36, 49) could not find implicit value for parameter converter: Converter[A,Int]
def fun1[A](a: A)(implicit arg: Arg[A]) = fun2(a, 42)
                                   ^
Error:(36, 49) not enough arguments for method fun2: (implicit converter: Converter[A,Int])String.
  Unspecified value parameter converter.
def fun1[A](a: A)(implicit arg: Arg[A]) = fun2(a, 42)
                                   ^

fun2 不知道 A 是什么。在这个例子中,从使用 fun1 A 显然是一个 Int 并且 B 也是一个 Int 并且存在一个隐式对象 IntIntConverter.我认为问题是 A 可能是任何东西,甚至不在编译代码中。

所以我尝试将 A 限制为 IntDouble 以便 Converter 可以用另一个类型类进行详尽枚举:

sealed trait Arg[T]

object Arg {

  implicit object IntArg extends Arg[Int]

  implicit object DoubleArg extends Arg[Double]
}

def fun1[A](a: A)(implicit arg: Arg[A]) = fun2(a, 42)

错误现在抱怨说这里不是 Converter[A,Int]fun1 并且我尝试了各种其他隐式变体,但我无法让 Converter 识别 [=29] 强加的约束=],因此永远无法为自己找到隐含的。

有没有什么方法可以定义它,以便fun2可以有一个通用参数,但它能够确定它需要包含哪个 Converter 实现?

你需要这样定义fun1

def fun1[A](a: A)(implicit converter: Converter[A, Int]) = fun2(a, 42)

在Scala中,类型推断没有"flow backwards",只有从左到右,从上到下。因此,fun1(1) 的使用不被考虑用于 fun1 的隐式解析——它不会将 A 固定为 Int。当编译器试图为 fun2 寻找 Converter[A, B] 时,编译器只看到它自己的函数定义,对 A 一无所知。它知道,B 必须 b 一个 Int,但在这一点上,A 可以是任何东西。因此,您必须为编译器提供它可以使用的正确类型 class:(implicit converter: Converter[A, Int])。现在,当调用 fun1(1) 时,编译器知道 A 并且可以查找 Converter[Int, Int].