-
Notifications
You must be signed in to change notification settings - Fork 14
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
Support as-patterns in pattern synonyms with view patterns #175
base: master
Are you sure you want to change the base?
Conversation
View patterns too, a tiny change on top of as-patterns. |
bdd9299
to
9fdc52f
Compare
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.
Thanks for the patch! I haven't had a chance to look at the finer details of how this works, but the general idea looks right.
Two possible ideas for making the generated code a bit more compact:
-
This:
pattern P x <- (id -> x)
Currently desugars to this:
pattern P x_1 <- (\arg_2 -> case arg_2 of viewed_3 -> case GHC.Base.id viewed_3 of x_1 -> x_1 -> x_1)
The first
case
expression isn't necessary, as it just binds a simpleviewed_3
. Nor isarg_2
used anywhere in the remainder of the expression. I think it should be possible to check if the very first pattern to be bound (viewed_3
, in this example) is a bareDVarP
, and if so, elide the intermediatecase
expression. -
Regarding your "uncomfortable unpacking/repacking" comment at Pattern guards are not a sufficient replacement for view patterns #174 (comment), what if instead of desugaring this:
data Foo a b = Foo a b pattern P x a b <- x@(Foo a b)
To this (cleaned up slightly):
pattern P x_1 a_2 b_3 <- ((\x_1 -> case x_1 of Foo a_2 b_3 -> (x_1, a_2, b_3)) -> (x_1, a_2, b_3))
We instead desugared to something like this?
pattern P x_1 a_2 b_3 <- ((\x_1 -> (x_1, x_1)) -> (x_1, Foo a_2 b_3))
That is, if a pattern doesn't contain any view patterns or as-patterns as subpatterns, then match on it in the pattern to the right of the
->
instead of matching on it in the expression to the left of the->
. This avoids having to unpack it in the expression on the left only to repack it again for the benefit of the pattern on the right.
I haven't thought deeply about how to implement these ideas, so I'm not sure if they work well with the current approach to desugaring patterns.
ok, I think I've addressed the comments, as well as added view pattern support everywhere (it fell out very naturally) I've keps |
err, actually I think there's a bug here I still need to sort! |
The bug here is that now do
let xs = [1,2]
x@1 <- xs
pure x This used to desugar to the equivalent of: do
let xs = [1,2]
1 <- xs
let x = 1
pure x But now it desugars to the equivalent of: do
let xs = [1,2]
x <- xs
let 1 = x
pure x Apart from it being incorrect, I do prefer the second one as there isn't any pattern -> expression transmutation happening. |
e7a4689
to
dbda940
Compare
OK. I could take a look, but there is currently a build failure in the patch, as caught by CI:
|
Ah, I didn't mean that I had uncovered an existing bug; I've introduced a new one. Before the "extra patterns" were designed/assumed to be infallible, but now they're not which leads to problems in do notation. It shouldn't be the end of the world to fix, although it's tempting just to reinstate the old "no view patterns" behaviour. |
OK. For what it's worth, I would be fine with reinstating the old behavior, opening a separate issue to track the remaining tasks. |
dbda940
to
ccb2de3
Compare
Ok, I reverted to the previous behaviour and opened #177 |
ccb2de3
to
0115daa
Compare
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.
Thank you so much for your continued work on this!
As one last suggestion, do you feel up to adding some test cases exercising this new functionality?
Language/Haskell/TH/Desugar/Core.hs
Outdated
(pat', vars) <- dsPatX pat | ||
(pat', vars) <- dsPat' pat |
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.
This changes the way that let
bindings are desugared, which is more ambitious than the title of the PR would suggest. I haven't thought deeply about this change, but could this potentially run into issues similar to the ones documented in #177? Or is this change fine because let
bindings don't treat fallible patterns the same way that do
-notation does?
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.
Good catch, it does actually change the meaning, however neither are always correct!
I've opened #178
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.
I'll keep the existing behaviour for now.
0115daa
to
24358d0
Compare
Thank you for taking the time for a thorough review @RyanGlScott! For the tests, it would be really nice to be able to describe them like so test_t175 :: [Assertion]
test_t175 =
fmap (uncurry (@=?))
$(do
Syn.lift =<< (traverse
(\(a, e) -> (,) <$> (sweeten @_ @[DDec] <$> (desugar =<< a)) <*> e)
[ ( [d| pattern P = (id -> ()) |]
, [d| pattern P = (\x -> case id x of () -> () -> ()) |]
)
, ( [d| pattern P x <- x@3 |]
, [d| pattern P x <- (\x -> case x of 3 -> x -> x) |]
)
, ([d| pattern P = ()|], [d| pattern P = ()|])
])
) But with something instead of |
Most of the unit tests are located here: Lines 77 to 154 in 92c07bd
Where each Lines 136 to 352 in 92c07bd
The problem with this approach is that it tests things by splicing in expressions. However, it's not entirely straightforward to define an expression containing a pattern synonym definition. You can't do something like One way we could accomplish this would be to define the pattern synonym definitions elsewhere, and then define expressions in terms of those pattern synonyms. We would need two copies of each pattern synonym: one using the original pattern synonym syntax, and another using the desugared syntax. We could define them in separate modules (similar to how we have both Testing alpha-equivalence would be another way to accomplish this, but nothing in |
How is this going, @expipiplus1? Do you need help with anything? |
Other life things have gotten in the way a bit! I would like to finalize this, but it's not at the top of my plate at the moment, sorry. I think there's also a bug, along the lines of: |
Thanks for the update! (I was worried that this was in a finished state and only being delayed due to figuring out how to add tests, in which case I could pick it up from there.) |
I guess a bit of a WIP, Maybe needs neatening and tests
See #174