编辑:我删除了过于复杂的示例,该示例仅为一个简单的问题模糊了问题
我正在试图弄清楚如何使用一个参数通用的方法为类型类提供必要的证据,但是可以从上下文中确定
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
,并且存在隐式对象{{1} }。我认为问题是IntIntConverter
可能是任何东西,甚至不在编译代码中。
因此,我尝试将A
限制为A
或Int
,以便Double
可以使用另一个类型类型进行详尽枚举:
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
识别Arg
强加的约束因此永远无法为自己找到隐含的东西。
有没有办法定义这个,以便fun2
可以有一个通用参数但是能够确定它需要包含哪个Converter
实现?
答案 0 :(得分:3)
您需要像这样定义fun1
。
def fun1[A](a: A)(implicit converter: Converter[A, Int]) = fun2(a, 42)
在Scala中,类型推断不会“向后流动”,只能从左到右,从上到下。因此,对fun1(1)
的隐式解决方案不考虑使用fun1
- 它不会将A
修复为Int
。仅查看函数定义本身时,编译器在尝试查找A
Converter[A, B]
时对fun2
一无所知。它知道,B
必须b
一个Int,但此时A
可能是任何东西。因此,您必须为编译器提供可以使用的正确类型类:(implicit converter: Converter[A, Int])
。现在,在调用fun1(1)
时,编译器知道A
并且可以查找Converter[Int, Int]
。