I read this comment in the NeoHaskell thread, on convenience in the Haskell ecosystem:
As it happens, I got a taste of some of these issues just yesterday. I thought I’d write up my experiences here, in the hope of spurring some discussion on these points.
My motivation yesterday was wanting to do a spot of data analysis. Nothing complicated: essentially, I just needed to plot some fields from a JSON file.
I first tried to do this in Haskell. The steps involved were, as I recall:
- Try to recall precisely which 10 packages I needed, and add them all to the Cabal file
- Start up Emacs… whoops, my set GHC version doesn’t have HLS, better change that…
- Add a
cabal.projectwith a more appropriate GHC version, remembering of course to fix the
- Start up Emacs again… wait, why is HLS using the wrong compiler version?
ghcup set ghc 9.2.7just to be completely sure
- Finally start writing code… oh wait, I forgot to add a package to do HTTP requests…
wreqto the Cabal file, restart HLS
- Start writing code for the second time… wait, why isn’t HLS reporting errors properly?
- Give up on HLS, use
cabal buildinstead to find type errors
- Finally make good progress, but find
Chartsa little too restrictive for my needs
At this point, I gave up on Haskell and reluctantly decided to try Python instead, where it went like this:
- Create a virtualenv
- Activate the virtualenv
pip install jupyter matplotlib
- Make good progress.
Now, I want to emphasise at this point that Haskell’s solutions are actually technically superior. Virtualenvs are a monstrous hack which should never have been necessary, and Jupyter is, let us say, not a great environment for editing. Meanwhile, Cabal and Emacs are both great pieces of software. Even comparing
matplotlib, it feels safe to say the former has the better design, even if
matplotlib is more featureful.
But, when it comes to convenience, Python wins hands down. HLS, for instance, is… not actually unstable, as such, but certainly requires a bit of care every now and then. (I still have no idea why it suddenly stopped working properly last night, though I’m sure I’ll figure it out eventually.) Having to remember to add the right libraries for your usecase —
aeson, wreq, lens, Chart, Chart-gtk, text, … — is a bit of a pain compared to Python’s ‘batteries-included’ standard library and ecosystem. And various things are incompatible in subtle ways which are only obvious to someone with more experience. (GHC version requires HLS version and
base version which affects other versions…)
So what’s the solution? I’m not entirely sure, but what I want is a workflow which looks something like this:
cabal initcreates a sane Cabal file, with a good set of default packages
cabal add Charts Charts-gtk wreqfor the extra packages
- Open up Emacs, and HLS works immediately with my compiler version
It would require a lot of coordination between community members, but I hope that something like this should one day be possible.
EDIT: On reflection, I’ve realised that most of the papercuts I mentioned are to do with HLS specifically. And, in particular, the fact that maintaining it for different GHC versions is a major pain. Perhaps we should direct more efforts towards solving this problem (though I know there’s work being done on the GHC API already).
EDIT2: Figured out the HLS error messages problem I mentioned earlier. It was because HLS was for some reason not detecting that I had a Cabal file, so it couldn’t find modules from my dependencies. Adding an
hie.yaml fixed the problem.
This, let me note, is yet another problem which requires a lot of experience to diagnose and solve. Ideally, beginners shouldn’t even need to know what an ‘HIE cradle’ is, let alone need to write one manually…