Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@adamgfraser
Copy link
Contributor

Adds support for optics to ZRef. Implements a new method foldS that allows access to the state in the modification function. This allows us to implement accessField and accessCase, which allow applying a lens or a prism to a ZRef, respectively. Also includes initial work on encoding of traversals.

Copying @Odomontois.

Comment on lines 365 to 380
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
}
Copy link

@Odomontois Odomontois Apr 2, 2020

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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)
Copy link
Contributor Author

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.

Copy link
Contributor Author

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])
Copy link
Contributor Author

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 {
Copy link
Contributor Author

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.

@adamgfraser adamgfraser requested a review from jdegoes April 2, 2020 12:19
@adamgfraser
Copy link
Contributor Author

@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.

@adamgfraser
Copy link
Contributor Author

Added support for using optics with transactional references.

@adamgfraser
Copy link
Contributor Author

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])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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])

?

😆

@adamgfraser adamgfraser requested a review from jdegoes April 8, 2020 00:10
* 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](
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

foldAll?

jdegoes
jdegoes previously approved these changes Apr 10, 2020
Copy link
Member

@jdegoes jdegoes left a 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.

@bmeesters
Copy link

Hello @adamgfraser , as a random bystander I am just curious on why the optics have been pulled out. Seemed pretty cool!

@adamgfraser
Copy link
Contributor Author

@bmeesters We are going to provide them as part of a separate zio-optics project. This will allow us to continue to evolve the API for this functionality after we guarantee binary compatibility for 1.0, fully explore what we can do with this without risk of bloating the core ZIO project, and allow users who want to use other optics implementations to do that. Look for more on this soon!

@jdegoes jdegoes merged commit de6c8c4 into zio:master Apr 10, 2020
@adamgfraser adamgfraser deleted the zref branch April 13, 2020 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants