3
sealed trait List[+A] // `List` data type, parameterized on a type, `A` case object Nil extends List[Nothing] // A `List` data constructor representing the empty list /* Another data constructor, representing nonempty lists. Note that `tail` is another `List[A]`, which may be `Nil` or another `Cons`. */ case class Cons[+A](head: A, tail: List[A]) extends List[A] 

My question is what is the "+" in front of A? Why in here "List[A]" the plus is ignored?

Thanks

2
  • 2
    stackoverflow.com/questions/663254/… Commented Nov 6, 2015 at 23:56
  • 2
    I read that well-written post, linked by Mr. V., a few times before understanding it. So don't be discouraged. Commented Nov 7, 2015 at 1:48

1 Answer 1

8

A plus or minus sign in front of a type constructor argument means that values of that type appear in covariant (+) or contravariant (-) position. A covariant position means the type only ever occurs as "output" or return type, as is the case with List. Then a List[A] is a subtype of a List[B] if A <: B, if A is a sub-type of B:

trait Animal { def food: String } case class Dog(name: String) extends Animal { def food = "all" } def test(xs: List[Animal]) = xs.map(_.food) test(List(Dog("Jussi"))) 

Here you can pass a List[Dog] for a List[Animal] because List[Dog] <: List[Animal].

Contravariance is the opposite - the type only occurs as input. For example Function1[A, Out] <: Function1[B, Out] if A >: B, if A is a super-type of B.

def test(fun: Dog => String): String = fun(Dog("Jussi")) test { x: Animal => x.food } 

Here you can pass a Animal => String for a Dog => String because the former is sub-type of the latter.


The variance annotation + or - only ever occurs in the definition of the type, so in the definition of List[+A], not anywhere else where List is used, e.g. as type ascription or in the extends clause, because the variance cannot change once it's defined. This is called definition-site variance.


Because Nothing is the bottom type in Scala, a type that is the sub-type of any other type, we can thus have the convenient object Nil extends List[Nothing], and thereby Nil becoming the sub-type of List[A] for any possible A. Whenever you need a list, no matter what the element type, you can use Nil.

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.