Question

As an exercise, I am supposed to implement a trait PartialOrdered[T].

trait PartialOrdered[T] {
  def below(that: T): Boolean
  def < (that: T): Boolean = (this below that) && !(that below this)  

  /* followed by other relations <=, >, >=, ==, .. */
}

A class K that extends this trait should have below implemented such that

a.below(b: K) = { true   if a <= b, 
                  false  in any other case

However, compiling gives the following error:

value below is not a member of type parameter T
def < (that: T): Boolean = (this below that) && !(that below this)
                                                        ^

So what am I missing? Thanks in advance

Edit: This is an example class Rectangle (in a coordinate system), with two opposing corners given, where a rectangle is below another if it is fully included

case class Rectangle (x1: Int, y1: Int, x2: Int, y2: Int) 
  extends PartialOrdered[Rectangle] {

  def below(r: Rectangle): Boolean = {
    val (rx, ry) = r.topLeft
    val (tx, ty) = this.topLeft
    tx >= rx && ty <= ry &&
    tx + this.width <= rx + r.width &&
    ty - this.height >= ry - r.height
  }

  def width: Int = {...}
  def height: Int = {...}
  def topLeft:(Int, Int) = {...}
}
Was it helpful?

Solution

You have to tell Scala that T is a subtype of PartialOrdered[T]:

trait PartialOrdered[T <: PartialOrdered[T]] { this: T =>
  def below(that: T): Boolean
  def < (that: T): Boolean = (this below that) && !(that below this)  

  /* followed by other relations <=, >, >=, ==, .. */
}

See also: scala self-type: value is not a member error

OTHER TIPS

You need two concepts here. One is F-bounded polymorphism, the other is self-type constraints.

F-bounded polymorphism, without going into the underlying type theory, is essentially what makes binary operators work. You basically define a trait to have its parameter be a subtype of itself:

trait PartialOrdered[T <: PartialOrdered[T]] {
  this: T =>
    def below(that: T): Boolean
    def <(that: T): Boolean =
      (this below that) && !(that below this)
}

To make not just this below that work, but also that below this, we further need to constrain the self-type. This is done via this: T =>, so that the compiler knows that this is also an instance of T, and not just PartialOrdered[T].

Then you define a class to use that trait. It needs to extend the trait with itself as the type parameter:

case class Pair(x: Double, y: Double) extends PartialOrdered[Pair] {
  def below(that: Pair) =
    x <= that.x && y <= that.y
}

object Program extends App {
  println(Pair(1, 2) < Pair(2, 0))
  println(Pair(1, 2) < Pair(1, 3))
  println(Pair(1, 2) < Pair(0, 2))
  println(Pair(1, 2) < Pair(2, 2))
}

T isn't necessarily an instance of PartialOrdered[T] so it doesn't have a below method. I think you meant

  def below(that: PartialOrdered[T]): Boolean
  def < (that: PartialOrdered[T]): Boolean = (this below that) && !(that below this)  

?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top