[SOlVED]Why complier cant recognize type from this code?

The code is following

    implicit def orderingList[Int](implicit ord: Ordering[Int]): Ordering[List[Int]] =
      new Ordering[List[Int]] {
        @scala.annotation.tailrec
        def compare(xs: List[Int], ys: List[Int]): Int =
          (xs, ys) match {
            case (x :: xsTail, y :: ysTail) =>
              val c = ord.compare(x, y)
              if (c != 0) c else compare(xsTail, ysTail)
            case (Nil, Nil) => 0
            case (r, Nil)   => if (r.forall(_ == 0)) 0 else 1
            case (Nil, r)   => if (r.forall(_ == 0)) 0 else -1
          }
      }

it will broken in IDEA and RPEL such as

Welcome to Scala 2.13.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_181).
Type in expressions for evaluation. Or try :help.

scala>     implicit def orderingList[Int](implicit ord: Ordering[Int]): Ordering[List[Int]] =
     |       new Ordering[List[Int]] {
     |         @scala.annotation.tailrec
     |         def compare(xs: List[Int], ys: List[Int]): Int =
     |           (xs, ys) match {
     |             case (x :: xsTail, y :: ysTail) =>
     |               val c = ord.compare(x, y)
     |               if (c != 0) c else compare(xsTail, ysTail)
     |             case (Nil, Nil) => 0
     |             case (r, Nil)   => if (r.forall(_ == 0)) 0 else 1
     |             case (Nil, r)   => if (r.forall(_ == 0)) 0 else -1
     |           }
     |       }
                     if (c != 0) c else compare(xsTail, ysTail)
                                 ^
On line 8: error: type mismatch;
        found   : c.type (with underlying type Int)
        required: Int
                   case (Nil, Nil) => 0
                                      ^
On line 9: error: type mismatch;
        found   : Int(0)
        required: Int
                   case (r, Nil)   => if (r.forall(_ == 0)) 0 else 1
                                                            ^
On line 10: error: type mismatch;
        found   : Int(0)
        required: Int
                   case (r, Nil)   => if (r.forall(_ == 0)) 0 else 1
                                                                   ^
On line 10: error: type mismatch;
        found   : Int(1)
        required: Int
                   case (Nil, r)   => if (r.forall(_ == 0)) 0 else -1
                                                            ^
On line 11: error: type mismatch;
        found   : Int(0)
        required: Int
                   case (Nil, r)   => if (r.forall(_ == 0)) 0 else -1
                                                                   ^
On line 11: error: type mismatch;
        found   : Int(-1)
        required: Int


However, when change Int to A, it works


What’s the problem?

This is quite a simple error. But it really surprises me, because I have seen many people make the same mistake; and I would really like to understand from where the confusion comes.

Now the error is here:

What you are saying here is that you are going to produce an Ordering for a List of ANY ARBITRARY TYPE which we well call Int (and you have just shadowed the type Int with your type parameter Int) as long as there is an Ordering for that type.
Whereas, what you really wanted to say was that you are going to produce an Ordering for a List of Ints.

You can fix the error by removing the type parameter [Int] from the declaration.

implicit def orderingList(implicit ord: Ordering[Int]): Ordering[List[Int]] =

Or even better, since we know there is an Ordering for Ints, we can just use a val:

implicit final val orderingList: Ordering[List[Int]] =

(and replace usages of orb with Ordering[Int])


Now, if you wanted to provide an Ordering for Lists of any type, as long as there is an Ordering for that type, you only need to use a different name so you do not shadow the Int type.

implicit def orderingList[A](implicit ord: Ordering[A]): Ordering[List[A]] =
  new Ordering[List[A]] {
    @scala.annotation.tailrec
    def compare(xs: List[A], ys: List[A]): Int = // ...
  }
2 Likes

Thanks for detail explain! @BalmungSan

1 Like

An error easy to understand, but also easy to make.

There’s the occasional [Int] in the wrong place, and then there is when you put [A] in a class definition and then also put an [A] in the definition of a method of that same class. Usually, the method definition compiles fine, and when you try to call it, you get confusing error messages.

Can we get a warning whenever a type parameter shadows an already defined type?

1 Like

Both of those conditions provoke warnings in 2.13 :tada:

6 Likes