无法找到参数的隐式值

3

我最近开始学习Scala的隐式“魔法”,但是在使用Scala隐式对象时遇到了问题。我尝试了所有可能的变量,但似乎没有什么效果。

假设我有一个这样的类,其中包含一些solve()函数。如果输入a,b为Float,则该函数应返回2个Float值。否则,它应返回另一种类型的值:

class Solver[T](val a: T, val b: T) {
    def solve[A](implicit num: customNumeric[T]): Option[(T, T)] = {
        Option(
            num.f(num.g(a)),
            num.f(num.g(b)))
    }
}

让我们假设another-type-value是这样一个类的对象:

class MyClass[T] (x: T, y: T)(implicit num: customNumeric[T]) {
    val field : T = num.f(x)
}

假设我没有我需要的基本Scala Numeric函数,那么我应该制作自己的自定义数值。

这是我所做的:

为我的自定义Numeric创建了一个抽象类,其中包含我的f()和g()方法,还有几个隐式对象扩展了我的customNumeric以处理一些值类型(例如Int、Float),并在它们中实现了方法:

abstract class customNumeric[T] {
    def f(x: T): T
    def g(x: T): T
}

object customNumeric {
    implicit object IntIsCustomNumeric extends customNumeric[MyClass[Int]] {
        def f(x: MyClass[Int]) = new MyClass[Int](x.field + 5)
        def g(x: MyClass[Int]) = new MyClass[Int](x.field - 5)
    }
    implicit object FloatIsCustomNumeric extends customNumeric[Float] {
        def f(x: Float): Float = x + 3
        def g(x: Float): Float = x - 3
    }
}

在我看来,Solver的solve()应该使用隐式的customNumeric对象来获取solve()内引用方法的实现,基于Solver输入值的类型。但是这并不起作用,因为编译器会报错:
could not find implicit value for parameter num: customNumeric[Int]
        def f...

在同一行,它也因为构造函数MyClass的参数不足而抱怨。

我已经尝试创建伴生对象将Int转换为MyClass

object Fraction {
    implicit def int2MyClass(x: Int): MyClass[Int] = new MyClass[Int](x, 1)
}

但是这似乎也不起作用。我尝试创建另一个隐式对象来实现我在customNumeric[MyClass[Int]]中使用的方法。

你有什么想法吗?谢谢!

2个回答

3
问题在于你试图使用需要相同隐式对象的类来定义隐式对象。

也就是说,这个:

class MyClass[T] (x: T, y: T)(implicit num: CustomNumeric[T])

需要存在一个隐式的CustomNumeric[T]。你不能使用该类型定义IntIsCustomNumeric

implicit object IntIsCustomNumeric extends customNumeric[MyClass[Int]]

当您实现 IntIsCustomNumeric 时,需要为类型 Int 实现它,而不是类型 MyClass[Int]。 当您这样做时,例如:

object CustomNumeric {
  implicit object IntIsCustomNumeric extends CustomNumeric[Int] {
    override def f(x: Int): Int = x
    override def g(x: Int): Int = x
  }
}

现在,您可以创建一个 Solver[Int],其中包含一个隐式的 CustomNumeric[Int]
def main(args: Array[String]): Unit = {
  import CustomNumeric._

  val solver = new Solver[Int](1, 2)
  println(solver.solve)
}

现在,从 Int 类型到创建 MyClass[Int] 的某个类型的隐式转换也变得更加容易:
implicit object MyClassIsCustomNumeric extends CustomNumeric[MyClass[Int]] {
  override def f(x: MyClass[Int]): MyClass[Int] = new MyClass[Int](x.field + 5)
  override def g(x: MyClass[Int]): MyClass[Int] = new MyClass[Int](x.field + 3)
}

implicit def intToMyClass(i: Int) = new MyClass[Int](i)

谢谢您提供如此详细的答案!我认为我明白了Solver将使用IntIsCustomNumeric对象,然后通过intToMyClass转换方法将其隐式转换为MyClass(具有方法实现)。但是,尝试调试此转换的执行使我想知道编译器如何知道是否应将IntIsCN转换为MyClassIsCN,因为IntIsCN具有完整的方法实现。因此,它可以仅使用IntIsCN的方法执行所有操作。还有一个问题-如果f(x:Int)不返回Int会怎样? - Random Guy

0

你对这个有什么看法?

object customNumeric {

  implicit object IntIsCustomNumeric extends customNumeric[Int] {
    def f(x: Int): Int = x + 3

    def g(x: Int): Int = x - 3
  }

  implicit object FloatIsCustomNumeric extends customNumeric[Float] {
    def f(x: Float): Float = x + 3

    def g(x: Float): Float = x - 3
  }

  implicit def int2MyClass(x: Int): MyClass[Int] = new MyClass[Int](x, 1)

  implicit object cn extends customNumeric[MyClass[Int]] {
    def f(x: MyClass[Int]) = x.field + 5

    def g(x: MyClass[Int]) = x.field - 5
  }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接