我需要帮助理解这种类型的签名:
def func[A : Ordering : ClassTag](a: A) = ???
我想出了使用上面类型签名的虚拟示例...以及我更熟悉的类型签名,我相信它是基于我的虚拟示例接近同一件事,但是我可以还提出一个玩具示例,显然是不一样的。
这两个看起来相似:
import scala.reflect.ClassTag
// type signature in question
def func1[A : Ordering : ClassTag](elems: A*) =
Array[A](elems: _*).sorted
// my typical type signature
def func2[A <% Ordered[A]](elems: A*)(implicit c: ClassTag[A]) =
Array[A](elems: _*).sorted
示例使用:
class BB(val i: Int) extends Ordered[BB] {
def compare(that: BB): Int = that.i - i
override def toString = s"BB(${i})"
}
func1(new BB(33), new BB(100), new BB(-1))
func2(new BB(33), new BB(100), new BB(-1))
输出的输出为:
Array[BB] = Array(BB(100), BB(33), BB(-1))
我可以提出的一个边缘情况与它们不同的地方...表明一个不仅是句法糖,是另一个的句法糖,是以下内容自然排序顺序。
此示例(下图(正常工作,implicit val ordering
覆盖了BB类的自然排序顺序,如我所期望的。
def func3[A <% Ordered[A] : ClassTag](elems: A*) = {
// opposite order defined in class BB
implicit val ordering: Ordering[A] =
Ordering.by{ case bb: BB => bb.i }
Array[A](elems: _*).sorted
}
此版本(下图(给我一个错误...
def func3[A : Ordering : ClassTag](elems: A*) = {
// opposite order defined in class BB
implicit val ordering: Ordering[A] =
Ordering.by{ case bb: BB => bb.i }
Array[A](elems: _*).sorted
}
错误:模棱两可的隐式值:两个值证据$ 1的类型排序[a] 类型排序的价值排序[A]匹配预期类型 scala.math.ordering [a]
因此,基于此...我猜: Ordering
将Ordered[BB]
转换为implicit val ordering
...或类似的东西?我的玩具示例无法透露更深的差异吗?
预先感谢。
:
类型参数是句法糖,用于声明隐式参数。在这种情况下,这意味着
def func1[A: Ordering: ClassTag](elems: A*) = Array[A](elems: _*).sorted
与
相同def func1[A](elems: A*)(implicit ordering: Ordering[A], classTag: ClassTag[A]) = Array[A](elems: _*).sorted
另一方面,func2
正在声明从A
到Ordered
的视图(<%
(。知道这一点的编译器可以召唤传递给sorted
方法的Ordering[Ordered]
最新版本的fun3
没有编译的原因是因为您在范围中提供了2个隐式Ordering[A]
:一个声明为fun3
的隐式参数和隐式Val ordering
。编译器不知道该选择哪一个并且对此抱怨,您应该删除其中一个以修复它。
无论如何,在实现这些功能时,介绍有关特定类型的代码不是一个好主意。对于任何不是BB
的类型,在创建Val ordering
中的模式匹配都会失败。
如果您的目标是定义特定的Ordering[BB]
,则可以在BB的同伴对象中执行此操作,然后将其加载到呼叫者函数的隐式范围中,如
class BB(val i: Int) {
override def toString: String = s"BB(${i})"
}
object BB {
implicit val ordering = Ordering.by[BB, Int](_.i)
val reverseOrdering = Ordering.by[BB, Int](-_.i)
}
然后,当您尝试订购bb时,它将默认选择隐式排序,但是您可以始终通过执行
来覆盖它implicit val ord = BB.reverseOrdering
Seq[BB]().sorted