-
Notifications
You must be signed in to change notification settings - Fork 71
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
Optics Rendering #1103
Optics Rendering #1103
Conversation
@lewisjkl, in the view of the size of the diff, I think it'd be worth having two different ways of enabling optics :
The inlined samples would only use the trait-driven one on a select few shapes (a struct, a union, an enum, etc) to showcase the feature |
* Allows abstracting over an optional target by pointing to | ||
* the inside of the optional value (the value inside of the [[Some]]). | ||
*/ | ||
final override def some[A0](implicit |
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.
👍
* Helper function for targeting the value inside of a [[smithy4s.Newtype]] | ||
* or other type with an implicit [[Bijection]] available. | ||
*/ | ||
final def value[A0](implicit bijection: Bijection[A0, A]): Lens[S, A0] = |
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.
👍
* Lens implementation which can be used to abstract over accessing/updating | ||
* a member of a product type | ||
*/ | ||
trait Lens[S, A] extends Optional[S, A] { self => |
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.
👍
@@ -15,8 +15,8 @@ object AddMenuItemRequest extends ShapeTag.Companion[AddMenuItemRequest] { | |||
val hints: Hints = Hints.empty | |||
|
|||
object Optics { | |||
val restaurant = Lens[AddMenuItemRequest, String](_.restaurant)(n => a => a.copy(restaurant = n)) | |||
val menuItem = Lens[AddMenuItemRequest, MenuItem](_.menuItem)(n => a => a.copy(menuItem = n)) | |||
val restaurantLens = Lens[AddMenuItemRequest, String](_.restaurant)(n => a => a.copy(restaurant = n)) |
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.
is it necessary to have the Lens
suffix ?
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.
Scala 2.12 was complaining that it couldn't tell if the name inside of the .copy(myName = ???) was the name of the parameter of the case class or the name of the val.. not sure if there is another way around this or not, but that's why I added the suffix to disambiguate
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.
strange, this seems to compile for me:
//> using scala "2.12.18"
trait Lens[A, B]
object Lens {
def apply[A, B](f: A => B)(g: (A, B) => A): Lens[A, B] = ???
}
case class Hello(name: String)
object Hello {
val name: Lens[Hello, String] = Lens[Hello, String](_.name)((c, n) => c.copy(name = n))
}
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.
Ahh the issue is that 2.12 needs the type annotation. The following fails:
//> using scala 2.12
trait Lens[A, B]
object Lens {
def apply[A, B](f: A => B)(g: B => A => A): Lens[A, B] = ???
}
case class Hello(name: String)
object Hello {
val name = Lens[Hello, String](_.name)(n => c => c.copy(name = n))
}
@kubukoz, Jeff and I tried to unify the rendering of Lenses/Prisms with Fields/Alts. Our conclusion is that trying for this unification requires way to many changes for little benefit, so we're gonna roll with this current PR, after Jeff syncs it with the latest 0.18 If you're curious about our attempt to unify, here's a diff (it introduces a bug that makes 4 aws-related tests fail, not gonna bother attempting to fix) :series/0.18...optics-in-fields-and-alts |
I appreciate the info! |
Adds the ability to render optics (Prisms and Lenses) in the generated code. The idea is that there will be very basic optic capabilities built into the smithy4s.core and then if users want something more advanced they can use implicit conversions to use something like monocle (see docs in the PR for more info).
Currently Lens instances are generated for structures and Prisms are generated for Unions and Enums.
For newtypes, I added a
.value
function on prisms/lenses that uses the bijection to automatically create a new lens/prism that targets the inner type of the newtype. I opted for this because then users can choose to create lenses/prisms that target the newtype or the inner type depending on their preferences. Lmk if you think there is a cleaner approach though.