我需要帮助理解这种类型的签名:
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
......或类似的东西?我的玩具示例是否有更深层次的差异无法揭示?
提前致谢。
答案 0 :(得分:1)
在类型参数之后的:
是用于声明隐式参数的语法糖。在这种情况下,这意味着
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
)。知道了这一点,编译器可以召唤传递给Ordering[Ordered]
方法的sorted
最新版本的fun3
未编译的原因是因为您在范围中提供了2个隐式Ordering[A]
:声明为隐式参数fun3
的隐式参数和隐式参数val ordering
。编译器不知道选择哪一个并且它抱怨它,你应该删除其中一个来修复它。
无论如何,在这些函数的实现中引入有关特定类型的代码并不是一个好主意。对于任何不是ordering
的类型,在创建val BB
时的模式匹配将失败。
如果您的目标是定义特定的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