-
Notifications
You must be signed in to change notification settings - Fork 162
Use (:>)
in favor of Cons
#2914
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
base: master
Are you sure you want to change the base?
Conversation
One of the reasons we couldn't remove the pattern synonym last time is that lazy pattern matches didn't work on GADTs. Is that still the case? Edit: if it is still the case, we could add an entry to the changelog saying users could use
to
|
Will this be a squash merge? Could you squash all commits and give it a good commit message? GitHub doesn't allow us to review the merge itself for some unfathomable reason, so I like to see the final product during review. |
6938cf2
to
3d80373
Compare
@kleinreact We talked about this a while ago, but I can't remember the conclusion. I think you said lazy patterns still work right? If so, is there anything blocking this PR that you know of? |
Lazy pattern still can cause problems (cf #2913 (comment)), which is why I for example also needed to change the type signature in The problem here more are the plugins, which don't work equally well with the constraints being introduced. My hope was that we could improve the plugins in that regard first, such that our users won't observe any difference, but that's bit more work, unfortunately. It's quite hard to estimate how much effect this particular change could have for our users. I'm fine with just trying it out 😉. |
So just to summarize my current understanding:
This PR associates the constructor |
Thanks for the write-up!
I've checked out your branch and tried to write a function that uses lazy pattern matches: f0 :: Vec (n + 1) a -> Vec n a
f0 ~(x :> xs) = xs but I get the error:
I was under the impression that you wanted to completely remove the pattern synonym, which would make it impossible to use lazy pattern matches. Is that not the case? Edit: it seems like The reason I'm hammering on this, is because if we completely remove the ability to do lazy pattern matches, we'd make it much more annoying to write circuits that "break the loop" so to speak, we'd break existing code bases, and our users would face issues like these. |
Yes, the idea is to swap the names of Would missing support for lazy pattern matches be a big deal though? You still can just use My problem here is that the pattern does two things: (1) it rewrites the match into a view pattern over the head and tail and (2) it introduces a new constraint. (1) is fine, but (2) can cause trouble. Most use cases won't need a lazy match in the first place, so just matching on the constructor instead should be fine. In some cases you might need a lazy match, i.e., (1), but then you probably don't need (2). Hence, my recommendation is to explicitly use a view pattern with I think that the user needs to explicitly take care of these difference here, and really only use lazy matching, if required. Currently we introduce a potential problem with every use of |
I don't see how f ~(x :> xs) into f (uncons -> (x, xs)) It's still a bit more verbose, but:
To be clear I just care about a clean, simple upgrade path for our users. There are big code bases out there. Minor changes like these just another thing on the pile of things they need to do in order to bump Clash.. |
I'm fine with the introduction of |
In any case, I'm excited to ditch the pattern synonyms! It's always been a wart, so thanks! |
The fact that we have to tell users to use lazy patterns for certain situations is already annoying enough, adding an extra step for I.e. my assumption is that more users will have to use a lazy pattern match for So the status quo, where it is easy to have a lazy match on |
I can totally see that @christiaanb. While I do think it's a wart, it's not truly a user-facing wart. Most people can go years without realizing |
Such constructions also have a nasty habit for working for vectors up to and including length 21, but not above, without raising Of course, if it works for a particular person, I won't stop them, absolutely not. It's just not what I'd recommend people use. And thus, I'm also not very concerned with something that is already fraught with details to be a bit cumbersome to use regarding constructors and pattern synonyms. |
We currently offer the
Cons
constructor and the(:>)
pattern synonym for vector construction. They slightly differ in their type signature and implementation, which can cause some code to work with one but not with the other and the other way around (cf. #2913).While the pattern synonym was necessary in the past to work around some GHC issues, these original problems are not not present with modern GHCs any more. Hence, it is desirable to favor the direct usage of the data constructor over the pattern.
Note that there are some conditional cases, where the currently differing type signature of the pattern may lead to less need for type annotations or explicit pattern matching on the constructor. This can be considered a side effect of the particular setup of the signature, which comes at the price that some code, which would check by using the data constructor instead, won't check with the pattern on the other hand. However, just requiring a bit more of annotation is a reasonable invest, as it usually leads to cleaner code. Consider for example this test case, that needed to be fixed for this change, where the resulting code resolved to be even easier to read than before.
In particular, the PR introduces the following changes:
(:>)
andCons
. The use of(:>)
is more popular thanCons
. Almost all our examples use it, which makes it to be favored in comparison toCons
.Cons
.Cons
pattern synonym is marked as deprecated, which will lead to only a single operation in the future.Still TODO: