3

I went through the documentation and found a couple of ways how to define ad-hoc behavior for type class instances. Here's the original example:

trait Ord[T] {
  def compare(x: T, y: T): Int
  extension (x: T) def < (y: T) = compare(x, y) < 0
  extension (x: T) def > (y: T) = compare(x, y) > 0
}

The funny thing is we could define a bunch of ordinary infix methods alongside with extensions. The user expected behavior should be the same (despite the implementation differences).

trait RankEq[T]:
  extension (x: T)
    def equal (y: T): Boolean

  extension (x: T)
    def notEqual (y: T): Boolean = !rankEqual(y)

trait RankOrd[T] {
  def rankCompare(x: T, y: T): Int

  def (x: T) isLower (y: T): Boolean =
    rankCompare(x, y) == -1

  def (x: T) isHigher (y: T): Boolean =
    rankCompare(x, y) == 1
}

Here's the example which illustrates that:

given rankEq as RankEq[Rank] {
  extension (x: Rank)
    def equal (y: Rank) = (x.ordinal - y.ordinal) == 0
}

given rankOrd as RankOrd[Rank] {
  override def rankCompare(x: Rank, y: Rank): Int = {
    x.ordinal - y.ordinal
  }
}

object Rank {
  def beats(r1: Rank, r2: Rank)
       (using RankEq[Rank])(using RankOrd[Rank]): Boolean = {
    
    if r1.equal(r2) then false    // extension methods
    else r1.isHigher(r2)            // trait-member infix method 
  }
}

Since both constructs are doing the same thing (in different ways), it rises a question: which way is the most idiomatic? If both, in which situations each works best?

Thanks!

4

1 回答 1

4
if r1.equal(r2) then false    // extension methods
else r1.isHigher(r2)          // trait-member infix method 

实际上,

trait RankOrd[T] {
  def (x: T) isHigher (y: T): Boolean
}

是扩展方法的前一种语法,并且

trait RankEq[T] {
  extension (x: T) def equal (y: T): Boolean
}

扩展方法的当前语法。

所以“特征成员中缀方法”是用前一种语法编写的扩展方法。

见提交

https://github.com/lampepfl/dotty/commit/6ff0ac8694d4e3b84ed9b15fb277f429c6767faa

我猜目前支持的两种语法都是暂时的。

于 2020-09-23T23:37:55.533 回答