0

Scala in Depth presents the following variance example.

scala> trait Function[-Arg, +Return] {
     |  def apply(arg: Arg): Return
     | }
defined trait Function

scala> val foo = new Function[Any, String] {
     |  override def apply(arg: Any): String =
     |    "Hello. I received " + arg
     | }
foo: Function[Any,String] = $anon$1@5db0e244

scala> val bar: Function[String, Any] = foo
bar: Function[String,Any] = $anon$1@5db0e244

What's the reason that we can assign foo to bar? I have a rough idea, but figured I'd ask outright.

Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384
  • possible duplicate of [Real-world examples of co- and contravariance in Scala](http://stackoverflow.com/questions/5277526/real-world-examples-of-co-and-contravariance-in-scala) – Kevin Wright Feb 19 '14 at 18:21
  • Seems like a valid question for me, and has my up-countervote. Even if there *is* an existing question that would help you here if you'd thought to search for the magic terms "covariance" and "contravariance" – Kevin Wright Feb 19 '14 at 18:24

1 Answers1

3

Exactly because the variance annotations make Function[Any, String] a subtype of Function[String, Any].

The covariance annotation, + means a narrower type argument yields a narrower constructed type and the contravariance annotation -, means a wider type parameter yields a narrower constructed type.

Randall Schulz
  • 26,420
  • 4
  • 61
  • 81
  • Ah, so `String` (-Arg) accepts its own type or super. Whereas `Any` (+Return) accepts its own type or sub-type? Is that reasoning legitimate towards understanding why the above `val bar ... = foo` works? – Kevin Meredith Feb 19 '14 at 17:07
  • Yes, that's basically it. Another corollary is: With no variance annotations, different parameter types yield *unrelated* constructed types regardless of the relationship between the parameters (if any). Other facts useful for reasoning about type compatibility include: Because the Scala type system is a full lattice, any two types have both a common supertype and a common subtype. Conversely any two types need not bear a supertype *or* a subtype relationship to each other. – Randall Schulz Feb 19 '14 at 17:27
  • 1
    It's easier to explain with timelords :) http://stackoverflow.com/a/5279656/165009 – Kevin Wright Feb 19 '14 at 18:27