-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Implement lens generation macros #5941
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
Comments
Thanks for looking into this! Another macro I wanted to implement but never got the time is GenLens equivalent for common fields of Coproduct e.g. sealed trait Foo
case class Foo1(name: String, i: Int) extends Foo
case class Foo2(name: String, b: Boolean) extends Foo
val name = GenLens[Foo](_.name) but it would fail if they were a 3 implementation of case class Foo3(x: Int) extends Foo |
I'm pretty sure the answer is "yes", but can you confirm for me that this generalizes to nested selectors, ie. |
good question, it would be awesome if it was. |
It's pattern matching on the Tasty trees, so I think it could be generalized and Just Work, but it'd be nice to be sure. |
@julien-truffaut There is some difficulty to implement the Coproduct lens in Dotty macros:
Even for the non-Coproduct Nested selectors |
Could you get it to typecheck by having the target type inferred as |
@milessabin The problem is that given the following macro signature: object GenLens {
inline def apply[S, T](get: S => T): Lens[S, T] = ~impl('(get))
} Dotty does not support only supplying 5 | val len = GenLens[Address](_.streetNumber)
| ^^^^^^^^^^^^^^^^^
| Not enough type arguments for GenLens.apply[S, T]
| expected: [S, T]
| actual: [Address] |
@nicolasstucki Any thoughts about this? |
In vanilla Scala the usual trick is something like, object GenLens {
def apply[S] = new MkGenLens[S]
class MkGenLens[S] {
def apply[T](get: S => T): Lens[S, T] = ...
}
} Then |
@milessabin Thanks a lot for sharing the trick, it works like a charm 👍 73524a7 |
I thought Dotty was supposed to solve those issues
…On Mon, Feb 18, 2019, 4:15 PM Fengyun Liu ***@***.***> wrote:
@milessabin <https://github.com/milessabin> Thanks a lot for sharing the
trick, it works like a charm 👍 73524a7
<73524a7>
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#5941 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAGAUJm3K3LFbyhjTf6kcNGbY5pwlETaks5vOxftgaJpZM4bAlx5>
.
|
You can write: val len = GenLens[S=Address](_.streetNumber) cf http://dotty.epfl.ch/docs/reference/other-new-features/named-typeargs.html |
Yeah, but that's really quite awkward in this sort of context (which is really quite common). It's a shame ... we ought to be able to do better. This works with poly functions, trait Lens[S, T]
def GenLens[S] = [T] -> (get: S => T) => new Lens[S, T] {}
case class Foo(i: Int)
object Test {
GenLens[Foo](_.i)
} But I think it would be nicer if we could support multiple type parameter lists, ie., def GenLens[S][T](get: S => T) = new Lens[S, T] {} |
Make a SIP :). |
With a PR attached ;-) |
The Unfortunately, we are unable to implement Code examples: val len2 = GenLens[Employee](_.addr.streetNumber)
val employee = Employee("Bob", Address(10, "High Street"))
assert(len2.get(employee) == 10)
val employee2 = len2.set(5, employee)
assert(employee2.name == "Bob")
assert(len2.get(employee2) == 5)
val jNum: Prism[Json, Double] = GenPrism[Json, JNum] composeIso GenIso[JNum, Double]
assert(jNum(3.5) == JNum(3.5))
assert(jNum.getOption(JNum(3.5)) == Some(3.5))
assert(jNum.getOption(JNull) == None) The implementation of |
@liufengyun the work I'm doing on generics will cover |
It would be nice to implement |
I started the implementation of Monocle for Dotty in the following repo: https://github.com/julien-truffaut/Monocly It would be amazing if any of you would like to participate or point me to some documentation. I tried to adapt the macro in https://github.com/lampepfl/dotty/blob/master/tests/run-macros/i5941/macro_1.scala but I am running into some issues. It is probably because I am using polymorphic optics (4 or 5 type parameters) and a curried set method. |
@julien-truffaut The following is the latest prototype implementation in Dotty https://github.com/lampepfl/dotty/blob/master/tests/run-macros/i5941/macro_1.scala . The documentation and the paper may also be useful. In your prototype, I think you should remove the def impl[A: Type, B: Type](getter: Expr[A => B])(given qctx: QuoteContext): Expr[Lens[A, B]] = {
implicit val toolbox: scala.quoted.staging.Toolbox = scala.quoted.staging.Toolbox.make(this.getClass.getClassLoader)
import qctx.tasty.{_, given} |
The following macros are used to cut down boilerplate when generating lens.
Links
Thanks to @milessabin for refering the macros to us.
The text was updated successfully, but these errors were encountered: