kenbot / goggles

Pleasant, yet principled Scala optics DSL
MIT License
196 stars 7 forks source link

Shortcut for Iso.id to introduce type in lens mode #31

Open kenbot opened 7 years ago

kenbot commented 7 years ago

Lens mode has to start with an interpolated optic, so that it knows the type to start with. If you want to start with something else, it's possible to put a monocle.Iso.id[MyType] in the leftmost position, which does the trick.

ie: lens"${Iso.id[Blah]}.foo.bar"

However, this has some problems:

One idea is to have a method with an obvious name (which one?) returning Iso.id, that is in scope with an import goggles._. With the right name this might arguably, barely satisfy "you already know how to use it", but wouldn't fix the performance.

Performance

Iso.id cannot itself be changed to override composition to just return the other thing, because the composeXXX methods are final, and should probably stay that way. However, if we make our own type that behaves exactly like Iso, we can make it have zero runtime overhead. While it essentially functions as a terminal object in the lens hierarchy, it might be better called "TypeHint" rather than "IdIso", which is its actual reason for existing. We could easily make the error tables omit or specially handle the "TypeHint" line at the start.

Code quality

A benefit here is that get/set modes could use this approach too, instead of the AppliedObject.const Unit <--> A Iso hack. This could mean more unified code with less special cases, and the generated code would be more recognisable Monocle code, with the object applied at the end. This would also improve their performance, as there would no longer be an runtime-unnecessary Iso at the start.

Naming

This is probably the hardest part of this ticket. There probably isn't a name that a typical user "already knows". Too rare, and it's just yet another obscure library curiosity. Too common, and there will be namespace problems for users.

Some examples: lens"${choose[Blah]}.foo.bar" lens"${select[Blah]}.foo.bar" lens"${selectType[Blah]}.foo.bar" lens"${typeOf[Blah]}.foo.bar" lens"${t[Blah]}.foo.bar" lens"${on[Blah]}.foo.bar" lens"${from[Blah]}.foo.bar" lens"${fromType[Blah]}.foo.bar" lens"${typed[Blah]}.foo.bar"

julien-truffaut commented 7 years ago

I am notoriously bad with names but I have a slight preference for from

kenbot commented 7 years ago

Thought here needs to be given to polymorphic optics usage; a PIso has 2 type parameters. Would there be a pFrom[S,T] alongside the from[S]? EDIT: between[S,T] seems a good name, wrt from. pFrom is consistent with Monocle's naming scheme though.

kenbot commented 5 years ago

What about a non-interpolated literal syntax like: lens"[Blah].foo.bar". It's pretty obvious what it means, but can we turn Blah into a real type just from the String? Would it need to be fully qualified, or can we access lexical scope?

This would be easy to add to the Parser as a new TypeHint AST node.