Scala多态类型特征,带有有序和classtag



我需要帮助理解这种类型的签名:

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]

因此,基于此...我猜: OrderingOrdered[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正在声明从AOrdered的视图(<%(。知道这一点的编译器可以召唤传递给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

最新更新