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中使用隐式证据.我在自己对这个问题的回答中详述了这个问题(也在下面).
=:=检查,如果两种类型的相等且FooInt和Int是绝对不相等,尽管存在这两种类型的值的隐式转换.
我会创建一个CanConvert类型类,可以转换A为B:
trait CanConvert[A, B] {
def convert(a: A): B
}
Run Code Online (Sandbox Code Playgroud)
我们可以创建类型的类实例变换Int成FooInt,反之亦然:
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)
| 归档时间: |
|
| 查看次数: |
81 次 |
| 最近记录: |