# Can we assign Functor of Some to Functor of Option

Here is the functor definition

``````  trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
``````

Question is:

``````    val optFunctor = new Functor[Option] {...}
val someFunctor = new Functor[Some] {...}

// can I do this ? If not why ?
val anotherSomeFunctor:Functor[Option] = someFunctor

whereas the following works

val x:Seq[Int] = ???
val y:List[Int] = ???
val z:Seq[Int] = y``````

If you try to compile this code, you will get a type mismatch error from the compiler, and it should also tell you

``````Note: Some <: Option, but trait Functor is invariant in type F.
You may wish to define F as +F instead. (SLS 4.5)
``````

Your `Functor` trait being invariant in `F` means, that a `Functor[A]` and a `Functor[B]` do not have any subtyping relation, regardless of any subtype relation between `A` and `B`.

The compiler suggests the fix of defining `F` as `+F`, which means making `Functor` covariant in `F`, so `Functor[A]` is a subtype of `Functor[B]` if `A` is a subtype of `B`:

``````trait Functor[+F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
``````

But this will also cause a compile error:

``````covariant type F occurs in contravariant position in type F[A] of value fa
``````

The reason is, that a covariant type may only be used in a covariant position, i.e as a return type (usually), but not as a parameter to a method (a contravariant position).

This rule is necessary, because you could have invalid code otherwise. A valid implementation for `Functor[Some]` could look like this:

``````new Functor[Some] {
def map[A,B](fa: Some[A])(f: A=>B): Some[B] = Some(f(fa.value))
}
``````

If you could assign this to a `Functor[Option]` value, the method on it would allow passing `Option`s, which do not have the `value` field (they may be `None` after all).

Regarding your example with `Seq` and `List`, you can see that `Seq[+A]` is covariant in its type parameter. You may wonder how this is possible, as the documentation contains methods like this:

``````def +:(elem: A): Seq[A]
``````

But the documentation is actually cheating here to make the signature look simpler. If you look at the source code, the real signature is

``````def +: [B >: A](elem: B): CC[B]
``````

so it takes any `B`, which is a supertype of `A`, and creates a collection of type `B`.

You will also note, that `Seq` does not contain any methods that mutate the collection. All mutable collections in the standard library are invariant in their element type, as their methods for adding need to take elements of the generic type.

More on variance can be found in the Scala Tour.

1 Like

Thank You. It all makes sense now.