1

My code

object TestApp extends App {   
  class A[T <: Ordered[T]] {
    def check(f: T, s: T) = f > s
  }    
  object A {
    def apply[T] = new A[T]
  }   
  A[String].check("ab", "aa")    
}

throws an exception:

Error:(13, 9) type arguments [T] do not conform to class A's type parameter bounds [T <: Ordered[T]]
    def apply[T] = new A[T]
        ^

But I don't understand why. For me, it seems ok. I have a class with type variable bounded with Ordered. In companion object, I'm trying to create an instance of A. But I'm not sure if my companion object has an access to the type variable of class A.

How can I fix it?

1 Answer 1

7

String doesn't extend Ordered in scala, it's just an alias for java.lang.String, plus your apply doesn't conform to the context bound you have in A (you accept any T there), you can work around requiring an implicit Ordering for that type:

scala> :pa
// Entering paste mode (ctrl-D to finish)

class A[T](implicit ord: Ordering[T]) {
  def check(f: T, s: T) = ord.gt(f, s)
}

object A {
  def apply[T](implicit ord: Ordering[T]) = new A[T]
}

A[String].check("ab", "aa")

// Exiting paste mode, now interpreting.

defined class A
defined object A
res0: Boolean = true

To show you that implicit conversions don't work for context bounds I made a small example:

scala> :pa
// Entering paste mode (ctrl-D to finish)

trait A
case class AA() extends A
case class CC()
implicit def conv(a: CC): A = AA() 

def f[T <: A](x: T): T = x
f(CC())

// Exiting paste mode, now interpreting.

<console>:23: error: inferred type arguments [CC] do not conform to method f's type parameter bounds [T <: A]
     f(CC())

As you can see the implicit I defined wasn't applied to CC to match the context bound.

Sign up to request clarification or add additional context in comments.

5 Comments

But String has implicit converter to StringOps which does extend Ordered trait.
implicit def augmentString(x: String): StringOps = new StringOps(x) in Predef
I can write class B { def check(f: String, s: String) = f > s } and it works.
@Finkelson Agreed, and in fact if you do something like val p: StringOps = "123" the implicit conversion from String to StringOps kicks in, but it won't to satisfy a context bound.
@Finkelson I added a small example showing that implicits don't kick in to satisfy context bounds.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.