optics-dev / optics-dev/Monocle

Use variance in optic type parameters

Open
#771 14 comments 0 reactions 1 assignee View on GitHub

@yilinwei is already working on this.

Since Jan 3, 2024.

3.x
Dominant language
Scala
Stars
1.7k
Forks
207
Avg merge
7h 59m
Merged PRs (30d)
5

Description

A Getter[A, B] is equivalent to A => B. So the variance of Getter should be the same as Function1, covariant in A, the input and contravariant in B, the output. If you are like me and have trouble putting your head around variance, you will find a great resource in Thinking with types.

trait Getter[-A, +B] {
  def get(from: A): B
}

On the other hand, a Lens[A, B] is equivalent to a pair of function (get: A => B, set: (A, B) => A). Both A and B appear in covariant and contravariant positions, which means Lens must be invariant in A and B.

trait Lens[A, B] extends Getter[A, B] { 
  // A is both an input and ouput of set
  def set(from: A, newValue: B): A 
}

All write optics are invariant, but it turns out that their polymorphic version is not. For example, a PolyLens[A1, A2, B1, B2] is a pair of function (get: A1 => B1, set: (A1, B2) => A2). Now, both A1 and B2 are in contravariant position and A2 and B1 are in covariant position.

trait PolyLens[-A1, +A2, +B1, -B2] extends Getter[A1, B1] { 
  def set(from: A1, newValue: B2): A2
}

Thank you, Adam Fraser and John De Goes for the idea. Also, thanks to Georgi Krastev for pointing out monomorphic Lens can inherit Getter with variance.

This issue is directly conflicting with removing polymorphic optics in #770.

So the question is, does variance in polymorphic optics brings enough benefits to compensate for their inconvenience?

EDIT: I removed the section where I said monomorphic Lens cannot inherit Fold with variance

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.