-
Notifications
You must be signed in to change notification settings - Fork 339
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
hlinting agda #4431
Comments
... and here are some examples:
If some of this code is machine-generated, then it would probably be better to fix the generator and reduce some of the common cases. Eg, pre-pending an element of a list using |
I'd be a bit careful with We should of course agree on a style, but it need not necessarily be the one of
Indeed, and not all of hlint's suggestions are improvements. Take f lots o arguments = do
a single long line The do is redundant, but it serves a purpose: One can now simply add a new line to f lots o arguments = do
a single long line
now a second line Not having to change other lines is good for minimal intrusion into the code, and keeping information delivered by Similar, case foo of
Aleph -> return $ f x
Beta -> return $ g x h iow sfll
Gamma -> return $ x
Delta -> return $ foo bar There is a redundant I'd rather not be bullied by mindless mechanisms. Taking suggestions, yes, but having to obey, no.
I think these examples should be viewed in their context. Some of hlint's suggestions are good, we can use them to improve the code. Some are bad, these need to be ignored. And many would not matter, I suppose. |
I agree with much of what you say, although the recommended way of using hlint is to generate a .hlint.yaml file based on your code that switches off all the diagnostics (hlint —default src > .hlint.yaml) and then switch on only those that are of interest. So I don’t recognise the threat of bullying. The question in this case is which those diagnostics are?! I also like to format my code uniformly using stylish-haskell, brittany, ormolu, etc. Again these are not always perfect, but they obviate the need to fuss with formatting while you are trying to get the substance right. |
Why? We don't all use the same style, and I don't see this as a problem. |
My straightforward question is which of the hlint hints is it safe to implement, and which would people prefer to ignore? (If the answer is “all of them”, I’ll let sleeping dogs lie.) |
Searching for the hint list, I found https://github.com/ndmitchell/hlint/blob/master/data/hlint.yaml or is there some better source? I once tried |
The list above comprises all the hints that occur in the current src directory. I wouldn't try the apply-refact package. Sometimes it works, sometimes not (which is why I'd like to test what people would find helpful before rolling up my sleeves). |
How to get hlinting started? I think a good way is to compose a list of uncontroversial hints, like e.g.
Or: join the Agda meeting and then this can be done interactively. As a higher-hanging fruit: implement feature kowainik/hintman#57 to get the hint-man use our own hint list. |
I don't think that it is worth making an industry out of this task. I don't think that we want 100 PRs to accomplish this task. To me,
I would argue that the first two categories are worth doing without much fuss (JDI). The third should either be reserved to a trusted member of the community that is willing to put in the time, on condition that everyone else agrees not to bike shed / quibble. But there are a lot of these potential changes across lots of files, and I would not trust apply-refact to get it right, so it requires some clear time and concentration to carry out what should be a mindless manual task once the right hlint settings have been applied (since hlint comes up with the refactoring suggestion). So it's not something that I'd want to embark on if it's going to create more angst than it solves. |
This doesn't always improve readability in my opinion (depends on the involved functions), and I believe GHC can do the fusion itself (no?), so performance shouldn't be an issue. |
In terms of lower-hanging fruit, there are a number of cyclic imports ( |
I suspect that ghc does a good deal of fusing, but probably not in all cases, and Agda doesn't build with -O2. Readability is subjective, but nested maps and foldrs are harder for me. |
A (stupid) example where the unfused version is more readable is: foldr (*) 1 . map (+1) which is clearly the multiplication of numbers after increasing them by one. The fused version foldr (\ x y -> (x+1) * y) 1 takes longer to comprehend, because one has to understand the anonymous function involved, convince oneself that the |
With some practice. foldr ((*) . succ) 1 can become as readable as the original version... |
After 17 years of Haskell, I still have to think what this means, and sort out which argument of |
That's why I mentioned practice — I am doing this kind of thing a lot... |
@jrp2014 commented:
Fusion rules are included in
|
Thanks for looking through #4448 Andreas. Working through that, and through the next tranche of candidates leads me to observe:
But my opinions are just that, not least since I haven't invested sweat in getting this project to its current state. Nevertheless, I do think that there is value in using a common set of idioms and, ideally a common layout format, both supported by automated tools. This is clearly not a new thought (not least because someone has configured a bot to hlint the PRs and the Makefile has an hlint entry). For formatting I use brittany / stylish-haskell / ormolu. None of these tools do a perfect job, but having at least local machine-supported uniformity must be a benefit. This comes back to which of the various hlint-guided idioms is worth scrubbing in? In my case, I prefer the most succinct code rendering (ie, dropping $ and () where they are not needed) as I think that that tends to be easiest to interpret in the long-run. I know that others like to rely on the visual layout of the code. (Much of the code would not be understandable by a new Haskell programmer no matter what you did, because it is lengthy.) We also need to think about the risk of making the code base harder to work with: changing the cosmetics can make it harder to bisect the case of future errors. |
Hi, I came across this issue from searching around, and probably ought to have found it earlier. I recently implemented #4802 (Add minimal hlint.yaml + GitHub workflow) because I had a >1yr old local branch with various hlint fixes that had grown stale, and I was interested in learning more about GitHub Actions. It looks like this issue had good discussion but was closed without reaching a conclusion. The tack I took in that PR seems to be in line here, which was to include an Since there was no resolution here I'll go ahead and re-open this issue and link it to that PR to for context. |
At present, the master code triggers just shy of a century of different types on hunting suggestions:
Many of these are purely syntactic (eg, redundant brackets, redundant do, redundant $, etc).
Some of them might improve readability (
\ _ -> fn
could beconst fn
, etc).Others suggest the use of more idiomatic style (Use null, maximum, intercalate, maybe, print, etc)
Others still suggest the use of simpler forms (eg, by fusion) or could well result in some performance improvements.
Now, it may be that people have strayed from hlint's suggestions because they used an older compiler or the thought that the current code is easier to read or it was machine generated. I'd be happy to have a go at some of the lower-hanging fruit, but thought it might be worth asking here why it might not have already been done. (The hacking guide is not specific enough to answer some of these questions and there is no
hint.yaml
file to suggest which hints should be ignored.The text was updated successfully, but these errors were encountered: