为什么我收到“无法找到参数 ord 的隐式值:scala.math.Ordering[T]”?

发布于 2024-10-14 10:34:54 字数 279 浏览 0 评论 0原文

我有一个简单的示例特征,它具有从 Ordered 派生的某种泛型类型的值。尽管我得到“无法找到参数 ord 的隐式值:scala.math.Ordering[T]”,但我找不到任何实际使用该值的方法。这是代码:

trait Example[T <: Ordered[_]] {
  val key: T

  def before(that: Example[T]): Boolean = (key < that.key)    
}

有什么想法为什么不能编译吗?

I have a simple example trait, which has a value of some generic type descended from Ordered. I can't find any way to actually use the value though as I get "Could not find implicit value for parameter ord: scala.math.Ordering[T]". Here's the code:

trait Example[T <: Ordered[_]] {
  val key: T

  def before(that: Example[T]): Boolean = (key < that.key)    
}

Any ideas why this doesn't compile?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白昼 2024-10-21 10:34:54

在我看来应该是这样

trait Example[T <: Ordered[T]] {

looks to me like it should be

trait Example[T <: Ordered[T]] {
听闻余生 2024-10-21 10:34:54

我相信,我不会编译,因为你说 T 应该在任何类型上排序。我们可以编写这样的等效特征(如果我错了,请纠正我 - 我不确定它是否可以被认为是等效的,但至少您会从编译器收到相同的错误):

trait Example1[A, T <: Ordered[A]] {
    val key: T

    def before(that: Example1[A, T]): Boolean = (key < that.key)
}

如果您查看Ordered 特征定义你会发现类似这样的东西:

trait Ordered[A] extends java.lang.Comparable[A] {
  ...

  def <  (that: A): Boolean = (this compare that) <  0
  ...
}

object Ordered {  
  /** Lens from Ordering[T] to Ordered[T] */
  implicit def orderingToOrdered[T](x: T)(implicit ord: Ordering[T]): Ordered[T] = 
    new Ordered[T] { def compare(that: T): Int = ord.compare(x, that) }
}

当我们根据这个定义来思考时 - 如果 keyOrdered[A] 比 < code>that.key 应该是 A 类型(根据 < 方法签名)。因此编译器实际上无法在 Ordered[A] 或换句话说 T 上使用它。如果我没有弄错的话,它会尝试找到一些可以用作最后手段的 Ordering[T] (根据伴生对象中的隐式定义)(但它失败了)。

因此,如果您像 T <: Ordered[T] 那样定义类型参数 T ,它将编译。

作为此问题的另一种解决方案,您可以使用上下文绑定,如下例所示:

abstract class Example[T: Ordering] {
  val key: T
  val ord = implicitly[Ordering[T]]
  import Ordered._

  def before(that: Example[T]): Boolean = key < that.key
}

var one = new Example[Int] {val key = 1}
var two = new Example[Int] {val key = 2}

println(one.before(two)) // prints: true
println(two.before(one)) // prints: false

在这种情况下,实际上会使用隐式转换,因为我们有证据表明 Ordering[T] 存在(特征不能有上下文)或视图绑定,所以我创建了抽象类)

这有意义吗?如果您发现我的逻辑有缺陷,请评论! (我会感激这一点)

I believe, I does not compile, because you saying that T should be Ordered on any type. We can write an equivalent trait like this (please, correct me, if I'm wrong - I'm not sure whether it can be considered equivalent, but at least you will receive the same error from compiler):

trait Example1[A, T <: Ordered[A]] {
    val key: T

    def before(that: Example1[A, T]): Boolean = (key < that.key)
}

If you look in the Ordered trait definition you will find something like this:

trait Ordered[A] extends java.lang.Comparable[A] {
  ...

  def <  (that: A): Boolean = (this compare that) <  0
  ...
}

object Ordered {  
  /** Lens from Ordering[T] to Ordered[T] */
  implicit def orderingToOrdered[T](x: T)(implicit ord: Ordering[T]): Ordered[T] = 
    new Ordered[T] { def compare(that: T): Int = ord.compare(x, that) }
}

When we will think in terms of this definition - if key is Ordered[A] than that.key should be of type A (according to < method signature). So compiler can't actually use it on Ordered[A] or in other words T. And if I'm not mistaking it tries to find some Ordering[T] (according to implicit definition in companion object) that can be used as last resort (but it fails).

So if you will define type parameter T like T <: Ordered[T] it will compile.

As another solution to this problem you can use context bound like in this example:

abstract class Example[T: Ordering] {
  val key: T
  val ord = implicitly[Ordering[T]]
  import Ordered._

  def before(that: Example[T]): Boolean = key < that.key
}

var one = new Example[Int] {val key = 1}
var two = new Example[Int] {val key = 2}

println(one.before(two)) // prints: true
println(two.before(one)) // prints: false

In this case implicit conversion would actually be used because we have evidence, that Ordering[T] exists (traits can't have context or view bound, so I created abstract class)

Does it makes sense? If you find flaws in my logic - please comment! (I will appreciate this)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文