optics-dev / Monocle

Optics library for Scala
https://www.optics.dev/Monocle/
MIT License
1.65k stars 205 forks source link

Use inheritance between optics #996

Closed julien-truffaut closed 3 years ago

julien-truffaut commented 3 years ago

Currently, Optics have a few methods asX, e.g. asTraverse, asOptional on Lens to "upcast" optics.

Instead, we could introduce inheritance between optics, e.g.

trait Lens[S, T, A, B] extends Optional[S, T, A, B] with Getter[S, A]

Then we can deprecate all the asX methods.

julien-truffaut commented 3 years ago

There is an issue with overriding modifyF

https://scastie.scala-lang.org/XVL7KRPEQo6wfRy3GgtUpw

jdegoes commented 3 years ago

Please do! 🙏

kenbot commented 3 years ago

I think inheritance "tells the truth" about the relationship between the optics. As long as it doesn't do anything crazy for type inference or variance or whatever, I think it's a good idea.

You shouldn't weigh this heavily at all, I signed up for difficulty, but it will certainly make Monocle 3 macro-writing slightly more convenient.

julien-truffaut commented 3 years ago

I made some progress but unfortunately it doesn't look good.

As @tpolecat told me in gitter, Scala doesn't accept narrowing on inputs https://gitter.im/scala/scala?at=602fd83b9ba13e72e43d7ea1

We could get around that by defining two version of modifyF for Lens, one that takes a Functor and one that takes an Applicative and write one in terms of the other. This trick works if all the arguments are within the same parentheses but it doesn't work if they are split over several parameterer lists :(

https://scastie.scala-lang.org/GPj1KhiBQnSsoXCACTLEVw

julien-truffaut commented 3 years ago

Since there is only one method affected: modifyF, maybe we could consider tto remove the overload and do:

trait Lens[S, T, A, B] {
  def foo[F[_]: Functor    ](update: A => F[B])(from: S): F[T]
  def bar[F[_]: Applicative](update: A => F[B])(from: S): F[T]
}

but I am not sure how to call foo and bar

joroKr21 commented 3 years ago

modifyF -> Functor and modifyA -> Applicative

julien-truffaut commented 3 years ago

Inheritance is overloading some methods because they have slightly different shape for optics with 2 or 4 type parameters, see https://github.com/optics-dev/Monocle/pull/1082.

julien-truffaut commented 3 years ago

Implemented in #1088