当调用者具有参数化值时找不到类型类隐式
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
限制为 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
识别 [=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]
.
编辑:我删除了过于复杂的示例,该示例仅混淆了一个简单示例的问题
我正在尝试弄清楚如何使用方法为类型类提供必要的证据,其中一个参数是通用的,但应该可以从上下文中确定
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
限制为 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
识别 [=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]
.