3

The line val a: Set[Fruit]=Set[Apple] does not compile, why ?

How can this be fixed ?

package sandbox.stackOverFlow

class Fruit 
class Apple extends Fruit
class Banana extends Fruit

class Why{
  val a:Set[Fruit]=Set[Apple]() // Does not compile, why ?
  val b:List[Fruit]=List[Apple]() // Does compile.
}

Produces compile error:

type mismatch;
 found   : scala.collection.immutable.Set[sandbox.stackOverFlow.Apple]
 required: Set[sandbox.stackOverFlow.Fruit]
Note: sandbox.stackOverFlow.Apple <: sandbox.stackOverFlow.Fruit, but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: sandbox.stackOverFlow.Fruit`. (SLS 3.2.10)
  val a:Set[Fruit]=Set[Apple]()
                         ^

EDIT:

As pointed out in Jatin's answer, this question is answered already here : Why is Scala's immutable Set not covariant in its type?

Community
  • 1
  • 1
jhegedus
  • 20,244
  • 16
  • 99
  • 167

3 Answers3

4

The type parameter of Set (even immutable) is invariant (mainly because Set[A] inherits from A => Boolean, which is contra variant in A). The type parameter of List is covariant.

As for how this can be fixed, the compiler gives you a potential solution: using a wildcard, such as

val a: Set[_ <: Fruit] = Set[Apple]()
Jean-Philippe Pellet
  • 59,296
  • 21
  • 173
  • 234
2

Because type parameter of List (declared as List[+A])is co-variant where as for Set (declared as Set[A]) it is invariant.

In short,

Co-variance is: converting broader type to narrow type (say converting List[Animal to List[Dog]. Contra-variance is converting narrow type to broader type. For example Function1[Dog, something] extends Function1[Animal, Something]. Here you are converting Dog (narrow) to Animal (broader)

Invariance does not give you permission to do nay of above.

There are several links available which explain co-variance and contra-variance:

  1. Why is Scala's immutable Set not covariant in its type? (@serejja mentioned this is comments)
  2. Why doesn't the example compile, aka how does (co-, contra-, and in-) variance work?
  3. http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/
  4. http://jatinpuri.com/2012/11/co-variance-contra-variance/
Community
  • 1
  • 1
Jatin
  • 31,116
  • 15
  • 98
  • 163
1

That's because Lists are covariant, ant Sets are invariant. Look at the definition:

sealed abstract class List[+A] extends...

trait Set[A] extends ...
serejja
  • 22,901
  • 6
  • 64
  • 72