How to paramaterize Int as Ordered in scala

后端 未结 2 1538
旧巷少年郎
旧巷少年郎 2021-02-04 01:30

I have a class with a parameterized type that I want to do comparison operators on. I assmue I need to use the Ordered trait to achieve this but the compiler doesn\'t like my us

相关标签:
2条回答
  • 2021-02-04 02:26

    This occurs because Int is not a subclass of Ordered[Int] (see here why).

    However, there is an implicit coercion from Int to RichInt which is a subclass of Ordered[Int], but it isn't triggered for lower bounds. Use <% (view bounds) instead which will consider implicit coercions:

    class Test[T <% Ordered[T]]
    
    0 讨论(0)
  • 2021-02-04 02:26

    You can use the Ordering[T] type class as an implicit parameter. If you wanted to write a generic max function, it would look like this:

    def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = { 
      if(ordering.gt(a,b)) a else b 
    }
    

    For the primitive data types like Int, Float, ..., there is an implicit Ordering[T] in scope so that you can use this as you would expect.

    max(1,2) // gives 2
    

    For all types that implement Ordered[T], there is also an implicit to provide an Ordering[T].

    There are also various methods in scope that combine orderings. For example if you have a N-tuple where each element has an Ordering[T], there automatically exists an Ordering for the tuple type.

    max((1,2), (3,4)) // gives (3,4) because 3 is larger than 1
    

    But if you are not satisfied with any of the implicitly provided orderings you can just write your own and pass it explicitly or even get it in scope as an implicit val. Like this:

    val negativeIntOrdering = new Ordering[Int] { 
      def compare(a:Int,b:Int) = b - a 
    }
    
    max(1,2)(negativeIntOrdering) // gives 1
    

    So the typeclass based approach is much more flexible than the inheritance based approach. This is why math libraries like spire use it extensively.

    One thing that is not as nice about the code above is that you have to use the lt method instead of an operator. But there is a solution for that as well. Ordering has an implicit method called mkOrderingOps that provides operators for T. You just need to get it in scope by importing ordering._, like this:

    def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = { 
      import ordering._; 
      if(a>b) a else b 
    }
    
    0 讨论(0)
提交回复
热议问题