简体   繁体   中英

Comparing values of a generic type in generic functions in Scala

The following function

def compare[T] (o1:T, o2:T):Boolean = {
   o1 > o2
}

will not compile, because value > is not a member of type parameter T

Defining the parameters to be of type AnyVal also does not work, and the compiler gives a similar error.

However, the function can only be called with values of type String and Long , which do support > .

What is the recomended soultion to write such a function?

Thanks

您可以像这样使用Ordering类型:

def compare[T](o1: T, o2: T)(implicit ord: Ordering[T]) = ord.gt(o1, o2)

If you want to use > operator you can use view bound with Ordered[T]

def compare[T <% Ordered[T]] (o1:T, o2:T):Boolean = {
  o1 > o2
}

There are good examples in scala docs.

http://docs.scala-lang.org/tutorials/FAQ/context-and-view-bounds.html

or you can do it with implicit parameter cause view bounds are deprecated now:

def  compare[T](o1: T, o2: T)(implicit ev: T => Ordered[T]): Boolean = {
  o1 < o2
}

If you want to avoid explicitly mentioning an implicit parameter, but also avoid using the now-deprecated view bounds, you can do it with context bounds like this, by defining a type alias:

type OrderedView[T] = T => Ordered[T]

def compare[T: OrderedView](o1: T, o2: T) = {
  o1 > o2
}

This pattern doesn't seem to be very well-documented, unfortunately - I found it on a post in the scala-internals mailing list when trying to work out how to implement the "enrich my library" pattern without using context bounds.

View bounds are deprecated, you should not use them, you can however use context bounds. This will give you implicit access to an ordering instance and you can use the compare method:

def compare[T: Ordering] (o1:T, o2:T):Boolean = {
  val ord = implicitly[Ordering[T]] 
  ord.compare(o1, o2) > 0
}

Now if you have to do this a lot directly using the operators is much nicer of course. Ordering directly provides an implicit conversion, that you can just import locally:

def compare[T: Ordering] (o1:T, o2:T):Boolean = {
  val ord = implicitly[Ordering[T]] 
  import ord.mkOrderingOps
  o1 > o2
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM