我一直在尝试隐式转换,而且我对使用这些转换的'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
}
当我运行上述方法时,我收到此错误:
Error:(31, 5) Cannot prove that nodescala.Moo.FooInt =:= Int.
x.swap
^
我很困惑,因为我认为我的范围内隐含转换足以“证明”Int可以转换为FooInt,反之亦然。在此先感谢我让我直截了当!
更新:
在下面的彼得的优秀答案中没有注意到之后,灯泡继续为我提供了一个很好的理由,你想在你的API中使用隐式证据。我在回答这个问题时也详细说明了这个问题(也在下面)。
答案 0 :(得分:5)
=:=
检查这两种类型是否相等,FooInt
和Int
肯定不相等,尽管这两种类型的值存在隐式转换。
我会创建一个CanConvert
类型的类,可以将A
转换为B
:
trait CanConvert[A, B] {
def convert(a: A): B
}
我们可以创建类型类实例,将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
}
现在我们可以在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)
}
我们可以用作:
scala> val x = new Pair(FooInt(200), 100)
x: Pair[FooInt,Int] = (FooInt(200), 100)
scala> x.swap
scala> x.dump
(FooInt(100), 200)
答案 1 :(得分:3)
Integer.parseInt("")
是不证明A可以转换为B.证明A可以是$variable = file_get_contents('your text file');
$data = explode(',',$variable);
到B.并且您没有任何隐含的证据证明可以反过来投射到FooInt(有充分的理由;)。
您正在寻找的是:
A =:= B
答案 2 :(得分:0)
在完成这个练习之后,我想我对为什么有了更好的理解,你想在你的API中使用隐式证据。
在以下情况下,隐含证据非常有用:
因此,在我原始问题中给出的简单API的情况下:
<timepicker ng-show="vm.date" ng-model="vm.time" ng-change="vm.pickTime()" show-meridian="false"></timepicker>
我们有一个类型Pair,它将两个东西放在一起,我们总是可以调用dump()来检查这两个东西。在某些条件下,我们还可以交换货币对中第一和第二项的头寸。这些条件是由隐含的证据约束给出的。
Scala编程书中给出了a nice example of how this technique is used in Scala collections,特别是关于Traversables的toMap方法。
这本书指出了Map的构造函数
希望键值对,即两元组作为参数。如果我们有 序列[Traversable]对,创建一个Map不是很好 一步走出他们?这就是地图的作用,但我们有一个 困境。如果序列不是,我们不允许用户调用Map 一系列配对。
所以有一个类型[Traversable]的例子,它有一个方法[toMap],不能在所有情况下使用......它只能在编译器可以“证明”(通过隐式证据)时使用Traversable中的项目是成对的。