hlint
hlint copied to clipboard
Add interactive HLint website
Give a page you can paste in text and get back HLint suggestions. Either just link to an existing paste site that does it, or write my own on top of the HLint API.
Here's a demo of something I put together this afternoon. It needs to be cleaned up (and it relies on a hacked version of ghc-exactprint) but I think it could be good..
http://gfycat.com/ComposedPotableEastrussiancoursinghounds
Very cool!
I like this a lot. What tech did you use? Haskell server or GHCJS?
I used servant. I tried to use GHCJS but it's hard to compile dependencies which depend on GHC.
Something based on GHCJS would be my preference, so we can skip server issues.
I have a sloppy but functional proof-of-concept up at https://lively-opaque-snipe.glitch.me/ using GHCJS, the code for which is here. I mostly followed the steps outlined in this blog post I wrote, and I had to make a couple of small changes to HLint:
- The
yamllibrary doesn't support GHCJS at all, so I switched to usingHsYAMLandHsYAML-aeson. - GHCJS doesn't seem to allow me to read files from the disk, so I used
file-embedto copy the contents ofhlint.yamlinto my app and used that instead.
The resulting app seems pretty laggy, because my Reflex-fu is weak and I'm probably using the HLint API in the simplest and slowest possible way, so it might not appear to work at first. I suggest trying with a warning-laden snippet of code such as:
module Main where
main = do
print $ "Hello world"
print $ "Does this work?"
and then editing the text until hints show up:

I'd love to know what you think and if this is useful at all.
Sweet!!!! This is awesome. Yep, it's a tad slow, but not that slow given what it's doing. I would have thought moving the parse/check compilation onto a separate background worker thread and cancelling existing compilations when a new one starts, or queuing them and deleting multiple ones, would have been sufficient. Two strands of thought here:
- How can we reduce the delta between your code and upstream, so it's easier to maintain.
- How can we make it better UI experience.
First one would be all about reducing the number of patches you have to maintain.
- Annoyingly, HsYAML is GPL licensed, or I'd just switch wholesale to it (I have asked if it can relicense). We could have a -ghsjs flag, and a GHSJS define, to make the switch.
- HLint already uses file-embed on the hlint.yaml file. You might just be able to remove that. Or maybe we don't have the API's available - we can investigate.
- I see you patched ghc-lib-parser. Is that patch necessary? If so, why? If that's all that stands between ghc-lib-parser working on GHCJS and not? If so, I imagine @shayne-fletcher would incorporate it into upstream ghc-lib-parser.
And to make the UI experience better, I suspect all these are on your list if it goes beyond proof of concept:
- A bit of polish around the layout, style.
- Probably want to use one of the JS editors that offers syntax for Haskell.
- Format the errors nicely.
But fundamentally, yes, this is exactly what I was after, and I'd be very happy to put it front-and-centre on the README/Cabal and advertise people to it.
Wonderful! I was envisioning something like ormolu-live and planning to reuse some of that code as well, but I thought it would be useful to get your feedback as soon as I got it minimally working so I could see if I was on the right track.
-
I figured the GPL license of
HsYAMLmight be an issue, this has come up when working with YAML and GHCJS before, and I personally like the approach of putting the HsYAML implementation behind a flag (or reusing thegplflag you already have). I was pleasantly surprised that switching over was so easy. -
I completely missed the
EmbedDatamodule you already have! I don't thinkhlintYamlis exported inLanguage.Haskell.HLintthough. OTOH the code I have to get the contents ofhlint.yamlseems pretty robust against future changes, so maybe nothing needs to change here? -
I had to patch
ghc-lib-parserbecause of https://github.com/digital-asset/ghc-lib/issues/204 (and I used the same workaround as https://github.com/digital-asset/ghc-lib/issues/204#issuecomment-623072347), which does seem to be an issue with the GHCJS build.
At the moment I'm only using the plain suggestions provided by HLint instead of the HTML ones and I've put no effort into styling or highlighting the input in the textarea (syntax highlighting, line numbers, etc.) so there's a lot of low-hanging fruit for me to work on.
ormulu-live looks like a great target.
- GPL behind a flag seems fine.
- EmbedData the way you have done it seems quite reasonable - maybe I can adjust the API to make it easier for you in future.
- Seems like universally patching ghc-lib-parser would be useful.
Awesome work thus far, super happy.
- I had to patch
ghc-lib-parserbecause of digital-asset/ghc-lib#204 (and I used the same workaround as digital-asset/ghc-lib#204 (comment)), which does seem to be an issue with the GHCJS build.
Maybe patching ghc-lib-parser to account for this is the right thing to do. Before we leap into that, it would be nice to exhaust the possibility that there isn't a better fix involving the GHCJS build system which is fairly obviously manipulating the C include path resulting in the eclipsing of the HsVersion.h that ships with ghc-lib-parser with a custom one. Maybe that's an intent of GHCJS but maybe not and if not, that other headers might be silently substituted for which the HsVersion.hs issue is a "canary in the coal-mine" worries me.
@shayne-fletcher - that is indeed the intention of the GHSJS build system - they try and shim out HsVersions.h with their own version so they can pretend to be a different version. But they weren't aiming to invalid ghc-lib, only GHC itself.
@ndmitchell Looking into the contents of HsVersions.h reassures me some that doing this is unlikely to have unintended consequences.
Fixed in ghc-lib-parser-8.10.1.20200518 (released).
I put this down for a while and when I picked it back up one of my dependencies had vanished from the internet :frowning_face:. I've just updated it to use CodeMirror for syntax-highlighted input, still at https://lively-opaque-snipe.glitch.me/.
Edit 1: It seemed to work before but is broken right now when I try it, sorry about that! Edit 2: Fixed now!
Still looks good - would be great to make available more widely :)
The repo is now at https://github.com/vaibhavsagar/hlint-live with the accompanying continously-deployed website at https://vaibhavsagar.com/hlint-live/. I'm not sure how much energy I can commit to doing all the fit and finish work that is required but I'm happy to accept contributions and/or transfer ownership to someone with more resources. I find it ironic that the most technically challenging part of this project (running HLint in the browser) was relatively easy but the least technically interesting/seemingly easiest things (adding CodeMirror, CSS, etc) are what I'm finding most difficult.
Thanks, this is a great start :)