Is Comparator a type class?

后端 未结 3 888
野趣味
野趣味 2021-02-08 02:55

I\'ve been reading up on type classes in Scala and thought I had a good grasp on it, until I remembered Java\'s java.util.Comparator.

If I understand proper

3条回答
  •  抹茶落季
    2021-02-08 03:24

    I prefer not to talk specifically about type classes but about the type class pattern in Scala; the reason is that when you start asking "what is the type class", you end up concluding that it is just an interface used in a particular way.

    (In Haskell it makes more sense to call a specific construct a type class.)

    The type class pattern consists of three essential parts (but there are usually a couple more for convenience). The first is an interface parameterized by a single type that abstracts some sort of capability on the parameterized type. java.util.Comparator is a perfect example: it provides an interface for comparison. Let's just use that.

    The second thing you need is a method that makes use of that parameterization, which you can specify with short-hand notation in Scala:

    // Short signature
    //             v------------------- "We must be able to find a Comparator for A"
    def ordered[A: java.util.Comparator](a0: A, a1: A, a2: A) = {
      val cmp = implicitly[java.util.Comparator[A]]   // This is the Comparator
      cmp.compare(a0, a1) <= 0 && cmp.compare(a1, a2) <= 0
    }
    
    // Long signature version
    def ordered[A](a0: A, a1: A, a2: A)(implicit cmp: java.util.Comparator[A]) = {
      cmp.compare(a0, a1) <= 0 && cmp.compare(a1, a2) <= 0
    }
    

    Okay, but where do you get that comparator from? That's the third necessary piece. By default, Scala doesn't give you Comparators for the classes you might like, but you can define your own:

    implicit object IntComp extends java.util.Comparator[Int] {
      def compare(a: Int, b: Int) = a.compareTo(b)
    }
    
    scala> ordered(1,2,3)
    res5: Boolean = true
    
    scala> ordered(1,3,2)
    res6: Boolean = false
    

    Now that you've provided the functionality for Int (implicitly), the compiler will fill in the implicit parameter to ordered to make it work. If you haven't yet provided the functionality, it gives an error:

    scala> ordered("fish","wish","dish")
    :12: error: could not find implicit value
    for parameter cmp: java.util.Comparator[String]
              ordered("fish","wish","dish")
    

    until you supply that functionality:

    implicit object StringComp extends java.util.Comparator[String] {
      def compare(a: String, b: String) = a.compareTo(b)
    }
    
    scala> ordered("fish","wish","dish")
    res11: Boolean = false
    

    So, do we call java.util.Comparator a type class? It certainly functions just as well as a Scala trait that handles the equivalent part of the type class pattern. So even though the type class pattern doesn't work as well in Java (since you have to explicitly specify the instance to use instead of having it implicitly looked up), from a Scala perspective java.util.Comparator is as much a type class as anything.

提交回复
热议问题