Scala comparing val val element with abstract type

im trying to figure out how to express the code below using abstract types, instead of using type parameters.

trait Key[T] extends Ordered[Key[T]] {
  val key:T
}

case class DoubleKey(key:Double) extends Key[Double] {
  def compare(that:Key[Double]):Int = this.key compare that.key
}

My current version is as follows:

trait Key extends Ordered[Key] {
  type K 
  val key:K
}

case class DoubleKey(val key:Double) extends Key {
  type K = Double
  def compare(that:Key):Int = this.key compare that.key.asInstanceOf[K]
}

But I'm not happy with the explicit cast to type K : that.key.asInstanceOf[K]. Are there better / other ways to achieve ordering of an abstract element using abstract types?

I also tried to make sure that the type that:Keyis Double:

def compare(that:Key { type K = Double } ):Int = this.key compare that.key

but this also fails because the compiler does not consider the comparison to be defined. In addition, is there a solution in which compareyou can transfer to a key key by restricting K (for example, type K <: Ordered[K])?

+3
source share
2 answers

Key, , . .

trait Key { type K ; val key : K }

object Key {
  type PKey[KK] = Key { type K = KK }
  implicit def keyIsOrdered[K <% Ordered[K]](lhs : PKey[K]) = new Ordered[PKey[K]] {
    def compare(rhs : PKey[K]) = lhs.key compare rhs.key
  }
}

case class DoubleKey(val key : Double) extends Key { type K = Double }
case class StringKey(val key : String) extends Key { type K = String }

REPL (nb. trat/object). , REPL ),

scala> DoubleKey(23) < DoubleKey(34)
res3: Boolean = true

scala> StringKey("foo") < StringKey("bar")
res4: Boolean = false

scala> StringKey("foo") < DoubleKey(23)
<console>:14: error: could not find implicit value for parameter ord: scala.math.Ordering[ScalaObject]
       StringKey("foo") < DoubleKey(23)
+1

, , , DoubleKey StringKey . DoubleKey(1.0) < StringKey("foo")

:

case class StringKey(val key:String) extends Key {
  type K = String
  def compare(that:Key):Int = this.key compare that.key.asInstanceOf[K]
}

StringKey("b") < DoubleKey(1.0) // ClassCastException

, , :

abstract class Key[K <% Ordered[K]] extends Ordered[Key[K]] {
  val key:K
  def compare(that:Key[K]): Int = key compare that.key
}

case class DoubleKey(key:Double) extends Key[Double]
case class StringKey(key:String) extends Key[String]

StringKey("b") < DoubleKey(1.0) // won't compile

, , Double String Ordered, .

+4

Source: https://habr.com/ru/post/1783642/


All Articles