Scala中可以转换为结构类型的通用方法

8

为什么我不能这样做:

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))
3个回答

9

由于你正在处理Array,所以需要ClassManifest

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)
}

在这种情况下,编译器的错误信息非常清晰。
编辑:
您实际上不需要将序列转换为数组。以下代码可以正常工作。
def compare[A <% { def toInt: Int }, 
            B <% { def toInt: Int }]
           (bs: Seq[A], is: Seq[B]): Boolean = { 
      (bs, is).zipped.forall(_.toInt == _.toInt)
}

1
奇怪...这个失败了:println(Message.compare(List(1, 2, 3), List(0, 0, 0))) - Hugo Sereno Ferreira
@HugoSFerreira :这确实很奇怪。非常抱歉,我不知道如何解决这个问题。 - missingfaktor
1
@HugoSFerreira: 这似乎是一个错误。 - missingfaktor

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中标准值相同的方式提供 Numeric 类型类的证据。

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不允许您将其与视图界限混合使用。

1
它在compare (List(2, 3), List(2, 4))处失败。 - Hugo Sereno Ferreira
1
你设置的视图边界要求类型A和B必须是具有隐式转换可用于带有toInt方法的结构类型的类。2、3等为整数,而Scala的Int类没有toInt方法。为了使其起作用,您需要定义一个基本上与我的示例类B相同的类,然后创建从Int到B的隐式转换函数。 - Dan Simon
implicitly[Int => { def toInt: Int }] 成功编译,但在运行时失败。 - missingfaktor
然而,Scala不允许您将这些与视图界限混合使用。尽管如此,这并不是解决OP问题的方法。 - missingfaktor

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