当调用者具有参数化值时,未找到类型类型

时间:2015-01-22 19:36:43

标签: scala typeclass

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

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

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显然是IntB也是Int,并且存在隐式对象{{1} }。我认为问题是IntIntConverter可能是任何东西,甚至不在编译代码中。

因此,我尝试将A限制为AInt,以便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实现?

1 个答案:

答案 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]