Open nikita-volkov opened 9 years ago
It occurred to me that if you wanted to support NamedFieldPuns then the syntax is ambiguous in expressions. {a, b = 3}
could be the function \a_1 -> {a = a_1, b = 3}
or the record {a = a, b = 3}
for whatever identifier a
is in scope. You could disambiguate with a different quasiquoter I suppose, or a very slightly different syntax if you want something to can be supported unambiguously without a quasiquoter.
Hmm... Getting trickier. We'll need to research on the subject.
You could disambiguate with a different quasiquoter I suppose.
I'd much rather avoid a quasi-quoter-based logic. We should develop a syntax which we would not have to change in case at some point we implement a preprocessor, or hopefully implement a GHC syntax extension.
I kind of assumed that was the goal. I thought it'd be nice to be able to postprocess the generated function (for newtypes mainly, but also for functions like foo :: {a :: Int , b :: Int , c :: Int} -> IO ()
. If you had something like {<expr>\b, c=3, a} ==> \x y -> <expr> {b=x, c=3, a=y}
, which could be used to convert anything expecting a record to a function with positional arguments in any order, without needing a lambda. Then if you had {\b, c=3, a}
as shorthand for {id\b, c=3, a}
you could disambiguate nicely even in the non-postprocessed case.
Then the syntax without the backslash character would indicate a record pattern/expression, and I think would handle both RecordWildCards and NamedFieldPuns cleanly.
EDIT: I guess full expressions wouldn't work that nicely, since {\x -> x^2\a} ==> \b -> (\x -> x^2) {a = b}
would look kind of bad, though just an identifier to the left of the \
would probably handle the important use cases. Granted, even ignoring the postprocessing case, {\a,b}
looks pretty nice to me to represent an anonymous function that returns a record.
Wait a second. I just realised that NamedFieldPuns
is about a pattern context. This proposal concerns an expression context. We can have both things interpret the same syntax!
They apply to both unfortunately. In an expression let a = 1 in {a} ==> let a = 1 in {a = a}
Oh..
Another option would be something like {\d,\a,c=3,b}
, if you wanted to be able to use NamedFieldPuns and lambdas together (to desugar to \x y -> {a=y, b=b, c=3, d=x}
for whatever b
is in scope.
Though NamedFieldPuns in an expression might cause issues in general; assuming the lenses are in scope and have the same name as the field then barring a special compiler rule for FieldOwner {a,b}
could try to parse like {a=lens (Field :: Field "a"), b=lens (Field :: Field "b")}
if a
and b
weren't being shadowed.
Problem
Unquote an expression of the following form
to
(Note the reordering of arguments).
Then it will be possible to use it like this:
Extras
This can be extended even further to allow to partially initialize the record. E.g.:
Credits for the initial proposal go to a Reddit user htebalaka. Thank you!