-
Couldn't load subscription status.
- Fork 1.4k
Implement Optics for ZRef #3258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| final def set(a: A): IO[EA, Unit] = | ||
| setEither(a).fold(ZIO.fail(_), value.set) | ||
| value.modify { s => | ||
| setEither(a)(s) match { | ||
| case Left(e) => (Left(e), s) | ||
| case Right(s) => (Right(()), s) | ||
| } | ||
| }.absolve | ||
|
|
||
| final def setAsync(a: A): IO[EA, Unit] = | ||
| setEither(a).fold(ZIO.fail(_), value.setAsync) | ||
| value.modify { s => | ||
| setEither(a)(s) match { | ||
| case Left(e) => (Left(e), s) | ||
| case Right(s) => (Right(()), s) | ||
| } | ||
| }.absolve | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was the main reason to add another type for foldS result in my PR.
These implementations are clearly more complex than older one, which can be significant in the highly concurrent use case.
And setAsync loses ability to delay modification.
So I felt like it's good to keep a somewhat performant version for simple mappings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes could definitely add this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to add subtype to optimize set and setAsync for derived ZRef instances where possible.
| type Ref[A] = ZRef[Nothing, Nothing, A, A] | ||
| type ERef[+E, A] = ZRef[E, E, A, A] | ||
|
|
||
| type ZLens[-S, +T, +A, -B] = (S => A, B => S => T) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could be more polymorphic here, allowing each of these optics to have a get error and a set error here, but then we would need some constructors that make it easy for users to lift simple optics into these more polymorphic types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could also allow us to support some other types of optics such as partial isomorphisms from ZIO Config.
| type ZLens[-S, +T, +A, -B] = (S => A, B => S => T) | ||
| type ZOptional[-S, +T, +A, -B] = (S => Option[A], B => S => T) | ||
| type ZPrism[-S, +T, +A, -B] = (S => Option[A], B => T) | ||
| type ZTraversal[-S, +T, +A, -B] = (S => List[A], List[B] => S => Option[T]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm encoding a traversal right now as a pair of functions S => List[A] and List[B] => S => Option[T]. The set operation can fail if the number of elements being set doesn't match the expected number of elements to be set in the structure.
| self.fold(identity, identity, c => Right(prism._2(c)), b => prism._1(b).fold[Either[Unit, D]](Left(()))(Right(_))) | ||
| } | ||
|
|
||
| implicit class TraversalSyntax[A, B](private val self: ZRef[Unit, Unit, A, B]) extends AnyVal { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one in particular feels like it could benefit from a more polymorphic encoding of the optics.
|
@Odomontois Would you take a look at this when you get the chance? I revised to incorporate your point about retaining the performance of the original version where possible and made it more polymorphic to support a wide range of optics. |
|
Added support for using optics with transactional references. |
|
Added documentation. |
| type Ref[A] = ZRef[Nothing, Nothing, A, A] | ||
| type ERef[+E, A] = ZRef[E, E, A, A] | ||
|
|
||
| type ZOptic[-SG, -SS, -B, +EG, +ES, +A, +T] = (SG => Either[EG, A], B => SS => Either[ES, T]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| type ZOptic[-SG, -SS, -B, +EG, +ES, +A, +T] = (SG => Either[EG, A], B => SS => Either[ES, T]) | |
| /** | |
| * A `ZOptic` is able to get and set a piece of a whole, possibly failing. In the most general possible case, | |
| * the set / get types are distinct, and setting may fail with a different error than getting. | |
| * | |
| * See more specific type aliases for concrete examples of what optics can be used to do. | |
| */ | |
| type ZOptic[-GetWhole, -SetWholeBefore, -SetPiece, +GetError, +SetError, +GetPiece, +SetWholeAfter] = | |
| (GetWhole => Either[GetError, GetPiece], SetPiece => SetWholeBefore => Either[SetError, SetWholeAfter]) |
?
😆
| * the state in transforming the `set` value. This is a more powerful version | ||
| * of `fold` but requires unifying the error types. | ||
| */ | ||
| def foldS[EC >: EB, ED, C, D]( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
foldAll?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks fantastic! Good to merge after mdoc passes.
|
Hello @adamgfraser , as a random bystander I am just curious on why the optics have been pulled out. Seemed pretty cool! |
|
@bmeesters We are going to provide them as part of a separate |
Adds support for optics to
ZRef. Implements a new methodfoldSthat allows access to the state in the modification function. This allows us to implementaccessFieldandaccessCase, which allow applying a lens or a prism to aZRef, respectively. Also includes initial work on encoding of traversals.Copying @Odomontois.