Last active
March 17, 2017 09:16
-
-
Save alexandru/e13c10adfdaef47078b3d19f843469a8 to your computer and use it in GitHub Desktop.
Scala's Covariance Rules are Maybe Incompatible with Higher-Kinds :-(
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import scala.language.higherKinds | |
| sealed abstract class Stuff[F[_], +A] | |
| case class Suspend[F[_], A](a: () => F[A]) | |
| extends Stuff[F, A] | |
| // This function fails compilation compilation with: | |
| // | |
| // found : Suspend[F,?A1] where type ?A1 <: A (this is a GADT skolem) | |
| // required: Suspend[F,A] | |
| // Note: ?A1 <: A, but class Suspend is invariant in type A. | |
| // You may wish to define A as +A instead. (SLS 4.5) | |
| // case ref @ Suspend(_) => ref | |
| // ^ | |
| def extract[F[_], A](source: Stuff[F, A]): Suspend[F, A] = | |
| source match { | |
| case ref @ Suspend(_) => ref | |
| } | |
| // Following that advice, if we declare Suspend as covariant in +A | |
| // error: covariant type A occurs in invariant position in type => () => F[A] of value a | |
| // final case class Suspend[F[_], +A](a: () => F[A]) | |
| // ^ | |
| // | |
| // The solutions I'm seeing now are: | |
| // | |
| // 1. make F[_] covariant (i.e. F[+_]), but this will exclude | |
| // useful F implementations from Cats / Scalaz at least | |
| // 2. make A invariant, but this violates user expectations | |
| // (e.g. Scala's collections are covariant) | |
| // 3. work with `asInstanceOf` everywhere, but this is also | |
| // pushing a lot of complexity and ugliness to the user, | |
| // since this ADT is public - not acceptable! | |
| // | |
| // Anything I'm missing? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment