I have the following code
def addKitten(kitten: Kitten): EitherT[Future, GenericError, UUID] = {
val futureOfEither = db.run { // returns a Future[Int] with the number of rows written
kittens += kitten
}.map {
case 1 => kitten.uuid.asRight
case _ => GenericError.SpecificError.asLeft
}
EitherT(futureOfEither)
}
Where SpecificError is a subclass of GenericError. For some reason it does not compile complaining that a SpecificError is not a GenericError. Is it right?
I mean, Either[A, B] should be immutable, so why not making it covariant? Am I missing something?
The same issue for XorT and OptionT was raised here. The reply was:
In Scala, variance has both positives and negatives (perhaps that's how they decided on variance notation! :P). These pros/cons have been discussed numerous times in various venues, so I won't go into them now, but in my opinion at the end of the day you kind of have to settle on "to each their own".
I think this "to each their own" perspective implies that you can't force variance on a type constructor. A concrete example is
scalaz.Freein the 7.0 series. It forces theStype constructor to be covariant. At the time I often wanted to wrap aCoyonedainFree. The most recent versions of Cats and Scalaz have theCoyonedaessentially built into theFree, so this particular use might not be as desired now, but the general principle applies. The problem is thatCoyonedais invariant, so you simply couldn't do this (without a mess of@uncheckedVariance)! By making type constructor parameters invariant, you may end up forcing people to be more explicit about types, but I think that it beats the alternative, where you can prevent them from being able to use your type at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With