不清楚为什么我的范围内隐含转换不被接受为"隐含证据"

Chr*_*ord 0 scala typeclass implicit-conversion implicits

我一直在尝试隐式转换,而且我对使用这些转换的'enrich-my-libray'模式有了很好的理解.我试图将我对基本隐含的理解与隐含证据的使用结合起来......但我误解了一些关键的东西,如下面的方法所示:

import scala.language.implicitConversions

object Moo extends App {

  case class FooInt(i: Int)
  implicit def cvtInt(i: Int) : FooInt = FooInt(i)
  implicit def cvtFoo(f: FooInt) : Int = f.i

  class Pair[T, S](var first: T, var second: S) {
    def swap(implicit ev: T =:= S, ev2: S =:= T) {
      val temp = first
      first = second
      second = temp
    }

    def dump() = {
      println("first is " + first)
      println("second is " + second)
    }
  }

  val x  = new Pair(FooInt(200), 100)
  x.dump
  x.swap
  x.dump
}
Run Code Online (Sandbox Code Playgroud)

当我运行上面的方法时,我收到此错误:

    Error:(31, 5) Cannot prove that nodescala.Moo.FooInt =:= Int.
      x.swap
        ^
Run Code Online (Sandbox Code Playgroud)

我很困惑,因为我认为我的范围内隐含转换足以"证明"Int可以转换为FooInt,反之亦然.在此先感谢我直截了当!

更新:

在下面的Peter的优秀答案中没有注意到之后,灯泡继续为我提供了一个很好的理由,你想在你的API中使用隐式证据.我在自己对这个问题的回答中详述了这个问题(也在下面).

Pet*_*ens 5

=:=检查,如果两种类型的相等且FooIntInt是绝对不相等,尽管存在这两种类型的值的隐式转换.

我会创建一个CanConvert类型类,可以转换AB:

trait CanConvert[A, B] {
  def convert(a: A): B
}
Run Code Online (Sandbox Code Playgroud)

我们可以创建类型的类实例变换IntFooInt,反之亦然:

implicit val Int2FooInt = new CanConvert[Int, FooInt] {
  def convert(i: Int) = FooInt(i)
}

implicit val FooInt2Int = new CanConvert[FooInt, Int] {
  def convert(f: FooInt) = f.i
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以CanConvert在我们的Pair.swap函数中使用:

class Pair[A, B](var a: A, var b: B) {
  def swap(implicit a2b: CanConvert[A, B], b2a: CanConvert[B, A]) {
    val temp = a
    a = b2a.convert(b)
    b = a2b.convert(temp)
  }

  override def toString = s"($a, $b)"

  def dump(): Unit = println(this)
}
Run Code Online (Sandbox Code Playgroud)

我们可以用作:

scala> val x = new Pair(FooInt(200), 100)
x: Pair[FooInt,Int] = (FooInt(200), 100)

scala> x.swap

scala> x.dump
(FooInt(100), 200)
Run Code Online (Sandbox Code Playgroud)