为什么我不能这样做:
def compare[A <% { def toInt: Int },
B <% { def toInt: Int }]
(bs: Seq[A], is: Seq[B]): Boolean = {
bs.toArray.zip(is) forall { p => p._1.toInt == p._2.toInt }
}
为了比较任何可转换为Int
的类型序列?我怎样才能实现类似的模式?
更新:这应该运行Message.compare(List(1.0, 2.0, 3.0), List(0, 0, 0))
答案 0 :(得分:9)
由于您正在处理Array
,因此您需要ClassManifest
s。
def compare[A <% { def toInt: Int } : ClassManifest,
B <% { def toInt: Int } : ClassManifest]
(bs: Seq[A], is: Seq[B]): Boolean = {
(bs.toArray, is).zipped.forall(_.toInt == _.toInt)
}
在这种情况下编译器错误消息不能更清楚IMO。
修改强>
您并不需要将序列转换为数组。以下工作正常。
def compare[A <% { def toInt: Int },
B <% { def toInt: Int }]
(bs: Seq[A], is: Seq[B]): Boolean = {
(bs, is).zipped.forall(_.toInt == _.toInt)
}
答案 1 :(得分:2)
当我删除不必要的toArray
def compare[A <% { def toInt: Int }, B <% { def toInt: Int }](bs: Seq[A], is: Seq[B]): Boolean = { bs.zip(is) forall { p => p._1.toInt == p._2.toInt } }
Class A{def toInt = 4}
Class B(i: Int) {def toInt = i}
compare (List(new A, new A), List(new B(3), new B(4))) //false
compare (List(new A, new A), List(new B(4), new B(4))) //true
将Seq转换为数组需要添加一个隐式ClassManifest,但Scala不允许你将它们与视图边界混合。
答案 2 :(得分:2)
问题所在的一个很好的例子似乎是这样做:
val a = implicitly[Int => { def toInt : Int }]
a(1).toInt
Scala 2.9.1在运行时代码的某个时刻爆炸 - 我只能认为这是一个错误。
您可以使用类型类来实现您正在寻找的效果:以下代码适用于您的所有示例:
def compare[A : Numeric, B : Numeric](bs : Seq[A], cs : Seq[B]) = {
(bs, cs).zipped.forall(implicitly[Numeric[A]].toInt(_) == implicitly[Numeric[B]].toInt(_))
}
这也应该比使用结构类型的版本更快。如果您需要添加自己的类型,应该可以转换为整数,您可以使用与https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/math/Numeric.scala#L1标准值相同的方式为数字类型类提供证据。