Ross A. Baker’s detailed exploration of “Understanding Scala variance” is essential reading for developers aiming to master Scala’s sophisticated type system. The article begins by clarifying the concept of variance and its significance in subtyping, using concrete examples like AuthedUser and Guest.

Covariance is explained through scenarios where types like List[AuthedUser] can be used interchangeably with List[User]. Contravariance allows functions such as encoders to process more specific types (AuthedUser) without issue. Invariance is introduced, detailing scenarios where neither type can be substituted for the other.

Key points of this blog post:

  • Covariance: Enables types like List[AuthedUser] to be used where List[User] is expected.
  • Contravariance: Allows functions such as encoders (Encoder[User]) to process more specific types seamlessly.
  • Invariance: Prevents types from being substituted for one another in certain contexts, particularly in scenarios involving both input and output.
  • Higher-kinded Abstractions: Includes Functor, Contravariant, and Invariant type classes with varying variance rules.
  • Variance Positions: Covariance is used for outputs (positive positions), contravariance for inputs (negative positions).
  • .widen: Used to safely cast between types that might not otherwise be compatible due to variance constraints.

Key points are discussed in depth, including higher-kinded abstractions and their variance rules. For instance, Functor[F[+]] allows adapting outputs of producers, while Contravariant[F[-]] adapts inputs for consumers. The article also covers how variance positions affect function arguments and return types. Nice one!

[Read More]

Tags scala java programming akka programming