Convenience in the Haskell ecosystem

This was my impression as well. I’ve tried to do data analysis in Haskell in a project that already had all the libraries included, was just testing performance of some algorithms. I could generate a plot after a while but with Python it was around 4-5 times faster to generate it (we had a python shell around the library, so I was fortunate to be able to test both).

Had a similar experience with diagrams vs just using Cairo in Python.

The Haskell libraries are safer, better designed, but also slower to get something up for single use. Sometimes now when I do something, I get a quick prototype in Python to see what libraries I need, and when this gets long I switch back to Haskell

3 Likes

This is one of the reason why I have given up on using external tools and haven’t even try HLS. I rely instead on little knows ghci commands :type-at, :uses and :loc-at.
.

I believe those commands has been merged from intero, leading to intero to be obsolete.
However, they are a bit tricky to call manualy but are easily to integrate in a text editor.

I use vim and tmux to load ghci and send command from vim to (via tmux) ghci.

Here is the code vim code to transform a visual selection to a ghci command

vnoremap <space>rt :call Haskell_type_at("type-at")<CR>gv
vnoremap <space>ru :call Haskell_type_at("uses")<CR>gv
vnoremap <space>rl :call Haskell_type_at("loc-at")<CR>gv
nmap <space>rT viw<space>rtv
nmap <space>rU viw<space>ruv
nmap <space>rL viw<space>rlv

function Haskell_type_at(mode) range
  " mode can be type-at uses loc-at
  let l:command = printf (":%s %s %d %d %d %d\n",a:mode,  expand("%:p"), line('.'), col("'<"), line("'>"), col("'>")+1)
  call TmuxSend(l:command)
endfunction
3 Likes
  1. Like maxigit, I have not experienced 80% of this hassle because I have never used HLS.

    On Emacs, both haskell-mode (but requires one single non-default setting) and dante already do 80% of what HLS does for less than 10% of the setup cost. (They both just call ghci’s :type-at etc. (To be sure, that approach requires :load to be successful; so I just add -fdefer-type-errors to help.))

  2. “Patches welcome.”

  3. The Haskell culture and the Python culture have a fundamental disagreement on two axes about libraries.

    1. compiler-stays-minimal vs batteries-included

      (You know what, a decade ago Haskellers actually tried batteries-included. Look for the history of “Haskell Platform”.)

    2. you-have-choice vs only-one-library-to-choose-from

7 Likes

I haven’t tried out haskell with emacs, but the easiest path to using HLS is to just use vscode. You don’t have to fiddle with hie files or anything of the like. You only need GhcUp and to make sure vscode knows where GhcUp is and everything else happens automatically.

I used to be an avid emacs user but I decided I wanted “easy street” for the rest of my days, so I switched over. I know vscode isn’t everyone’s cup of tea, but if you give it a try, you’ll find vscode + haskell works wonderfully well.

1 Like

I think HLS is kind of overkill for smaller projects. ghci can take you quite far.

And the on-ramp to a new Haskell project is quite smooth if you use ghci. I don’t consider adding packages to a cabal/package.yaml file to be especially onerous.

1 Like

Having to fiddle with hie.yaml files really shouldn’t be dependent on the editor. Indeed, for about two years now, writing a manual one shouldn’t be necessary for all but the most esoteric setups.

1 Like

For the people here who are saying HLS isn’t necessary: you’re not wrong, but recall this thread is about convenience. It’s entirely possible to develop a project without HLS, and I’ve done so myself many times, but having proper editor integration is a far nicer experience.

I’m proposing something quite different to the old Haskell Platform: not a set of globally available packages, but merely a Cabal file template with a curated list of useful dependencies. The latter seems very reasonable to me, since it imposes nothing on the Haskell community at large: it just provides a starting point for a project, if one so chooses.

6 Likes

I’m not entirely convinced by this argument. If you start out with a blank .cabal file with only base, then you must add additional libraries (even boot libraries that will always be available). However, if cabal-install defaulted to adding a few of the more popular boot libraries, then it would be a little easier to get started. In a lot of cases, you wouldn’t have to remove packages.

You’re 100% correct that people would complain about having to remove packages, but my guess is that overall, it would remove more friction for more users than it would create.

Of course, trying to come up with which libraries to add by default to would likely lead to a lot of bike-shedding.

I completely agree with this as well, but I imagine you’re underestimating the importance of the default template.

It is hard to have any sort of meaningful discussion here without data, but I’d guess that cabal init or stack new would be called without the --with-template argument (that is to say, just using the default template) at least 75% of the time.


The basic argument I’m trying to make is that the default template is likely pretty important, and adding a few of the popular boot libraries would likely remove friction, at least when aggregating over all users.

8 Likes

A possible compromise: cabal init is interactive, so as the first question, ask for a template to use.

As a matter of fact, it basically already does this: it’s just that the available templates are limited to ‘library’, ‘executable’, ‘library and executable’, and ‘test suite’.

6 Likes

Agreed. I don’t at all mean that hls isn’t without its faults; it should work effortlessly in atleast all of the major editors. I was just writing to make it known that there’s at least one setup where HLS does work with the level of convenience we’re hoping to see in the Haskell ecosystem.

At work we have our own build system, we don’t use cabal. But one of the things it does is automatically include a small hardcoded set, such as text, mtl, vector and some others. It’s hardcoded for everyone and not configurable. I’ve never regretted that, and in fact I tend to forget those are not technically built in. As a contrast with cabal, the build file for an executable starts one line: haskell.executable { main = ./Thing.hs; private = [./Mod.hs Mod2.hs]; }

Part of the reason is that there is an ambient set of globally pinned versions, while cabal must live in the more complicated multi-version world. But, one line! Cabal buries me in bureaucracy about licenses and versions and descriptions and haskell language version and yes I want base and blah blah blah.

Back in cabal v1 days it was actually 0 lines, install what you want and ghc --make. Yes I know it led to its own problems and I’m not sure but cabal v2 may finally have a way to emulate the old way, but I don’t mind delaying the bureaucracy until I actually need it… and it turns out usually I don’t, since most stuff never goes to hackage.

While I’m complaining about cabal, does it still not have a way to generate the deps list from the imports? Or maybe someone wrote one and it could get integrated? Especially because in haskell module names can have nothing to do with the package name, that seems ripe to automate. I have imports automated for decades now, if I had been using cabal during that time I would probably have come up with another program to generate the import → package mapping.

1 Like

Not as far as I know. That feature sounds like a good one, and a natural extension of HLS’s feature to automatically import modules that provide the identifiers that you use.

1 Like

Are folks aware of static-ls? I’ve never used it, but it sounds like it fits the bill.

The goal of static-ls is to provide a high-speed, low-memory solution for large projects for which haskell-language-server tends to take up too much memory on recompilation.

5 Likes

This is the first I’ve heard of it, and it looks great! I’d be very happy with this as a fallback when HLS doesn’t work.

The main reason I am not using HLS is I don’t know how long it will leave. I have been doing Haskell for 20 years and I have seen countless cool projects going abandonware : ghc-mod, ghc-mod-ide, intero. In fact, the only stable tools are canal and ghc/ghci (sorry for the stack team).
Whatever people are telling me, I have no guarantee that ghcup and HLS will be still there in 5 years time (it takes 9 months to make a baby and then people realize that it is there main priority).

The only long term solution seems to merge HLS feature into ghci (with maybe a system of external plugins for exotic features). Of course if we think LSP is a long term solution itself.

2 Likes

So… I know this is all sorts of horrible, and I’m not suggesting the implementation resemble it at all, but for scaffolding a few general purpose project types with sensible defaults, could we take inspiration from:

1 Like
  1. fairly standard
  2. I’m afraid I don’t sympathize with that… unless you want our tooling to have fuzzy AI logic and guess what you might want
  3. Right… this is fixed in the VSCode haskell extension. It figures that out automatically. You can re-implement that logic for Emacs. Or use VScode haskell.
  4. Not really necessary usually
  5. That’s an issue with your editor, imo
  6. try: ghcup run --cabal latest --ghc recommended --hls latest --install -- emacs . (there’s a policy in ghcup and HLS projects that the recommended GHC always is supported by the latest HLS)
  7. your fault :stuck_out_tongue:
  8. HLS shouldn’t have to be restarted for that, imo… if it still can’t do this, there’s probably already a bug report on HLS issue tracker… maybe @fendor remembers
  9. yes, why isn’t it? Did you debug it on the cli? Troubleshooting — haskell-language-server 2.2.0.0 documentation

Overall:

  • yes, there are still rough edges and integration issues with some tools
  • some of those integration issues are the responsibility of the editor
  • ghcup can provide a temporary “virtual env”: see ghcup run --help (this logic is heavily abused by VSCode haskell extension)
3 Likes

Exactly my point! The whole reason I made this thread is to bring attention to the fact that rough edges exist, and to brainstorm some ideas about how to smooth them out a bit (so to speak).

True, but the editor is part of the tooling. (An extremely important part!)

I’m not too familiar with this tool; how is it different to, say, Stack templates?

2 Likes

Yes and HLS/GHCup devs are only involved in the VSCode Haskell extension, because that seems to yield the biggest return. If you want a similarly smooth experience for Emacs/Vim etc., you’ll have to start a project and attract contributors.

Fair enough. There’s still plenty else that can be improved, though.

1 Like