Stack and HLS, questions about the present and future

Hi folks! I’m a relatively new Haskeller (2-ish years), and I’ve used Stack for most of my projects so far. I love the isolation, the reproducibility of builds, the UX generally… it all works great for me. I’m a fan of hpack, Stackage, and its other ancillary bits as well.

EXCEPT. It is so frustrating to use Stack with HLS. The issues are well-documented (in the HLS docs, on Github, on various comments here, etc.) and seems to be pretty widely acknowledged.

I don’t want to get into specific “fixes” in this thread – I’ve tried all the magical incantations of restarting the language server, restarting my editor, defining an hie.yaml, deleting caches, stack purge && stack build and restart everything again, and so on. Sometimes it works, sometimes it doesn’t. Even when it does, it’s very disruptive.

So what I’m really wondering is:

  • Is there hope for the Stack/HLS issues being fixed? Or a better question: is there any active work on this problem currently? I’ve found this issue on the Stack GH page which seemed very promising until I realized it hadn’t been touched in a year.
  • Do people still recommend Stack at all? If so, how do you actually develop with it? Do you use HLS? Just grin and bear the issues?
  • Do people still recommend Stack for new Haskell users? I personally ran into issues immediately using Stack and HLS… the default “stack new” project has multiple components and is therefore broken (with HLS).
  • Can/should we raise the visibility of this issue for new users? And how? I feel like we should be shouting this from the rooftops. As a new user, I was utterly confused about the obtuse-sounding errors I’d get using the recommended (at least at the time) “default” Haskell toolchain. And my searches yielded years-old, still-open Github issues with no clear path forward for me as a user.

I don’t yet feel equipped to help as a developer, but I’m hoping posting this here will at least aid with the visibility a bit, if new users come across this. Or maybe prod the discussion along a bit.

Also, this might be impossible, but… I would love if some of the folks involved could help give more definitive insight, like: “Oh yeah, we’re working on that but it’s a HUGE effort and will take years” or “No, that’s back-burnered, don’t hold your breath,” etc. I think that would help people starting new projects or researching the effort to switch from Stack to Cabal.

Anyway… sorry for the long-winded post. I appreciate any insights you all might have!

9 Likes

My experience that HLS is just very flaky; even with cabal (and, for completeness, emacs+eglot),. For me it’s more often broken than not. Admittedly, I’m typically working on a pretty large project with multiple sub-libraries, testcases, and exectuables. It may work smoother on smaller projects.

As for your other question: I don’t bother with stack anymore. I find cabal more pleasant these days. (Although it unfortunately also still has many UI quirks).

3 Likes

I think it ultimately boils down to: follow the money/labour.

A bunch of the recent improvements to HLS when using cabal were part of the “multiple-home-units” project carried out by Well Typed. I don’t know the details, but I assume that part of the project goal was getting that through the tools that the project sponsor used, which I guess must have been cabal and HLS.

This work could certainly benefit stack (and then HLS-using-stack). But

  1. It’s a lot of work for a volunteer, and I think both cabal and stack are low in committed, high-power, long-term volunteers.
  2. Nobody has paid for it. Stack lost its corporate sponsor once FPComplete moved on, and clearly nobody has paid WT to do it (yet?).

So there it is. I for one am grateful that there is enough money that even one of our build tools can get some attention. Not too long ago the situation was dreadful everywhere, now it’s non-dreadful sometimes. That’s an improvement, even if it’s not very satisfying for the people still in the dreadful zone :frowning:

16 Likes

That’s a big part. But there’s another part that’s commonly overlooked in open source projects: maintaining invariants.

Even if you’d pay people to fix stack support, you still need maintainers who care to keep it working and have the awareness which decisions may impact their different types of users.

That part is less of a money driven issue, imo. It’s project priorities. Cabal (the library) has often caused churn for stack, because there was just little to no regard for them as important end users.

I think that has improved. For those things to improve the projects have to talk to each other.

When it comes to HLS, it’s really a lot of small annoying details. Lots of parts of HLS are still a giant hack (hie-bios etc) and we simply lack clean interfaces from both cabal and stack.

7 Likes

Ahhh, I see. That is great context to have. And exactly the kind of thing I was hoping this post would scare up! Thank you! I definitely wasn’t privy to who’s investing in what… or who’s not, as the case may be.

Sounds like the Stack/HLS situation is not super likely to drastically improve in the near future, in other words.

I for one am grateful that there is enough money that even one of our build tools can get some attention. Not too long ago the situation was dreadful everywhere, now it’s non-dreadful sometimes. That’s an improvement, even if it’s not very satisfying for the people still in the dreadful zone :frowning:

Well said! I do think improvement is improvement, even if it isn’t ideal. And it’s certainly helpful to have a more concrete/realistic idea of the state of things.

Hate to ask the question, but I wonder at what point Stack should stop being suggested by default to new users, e.g. on the downloads page

I don’t use stack personally and have always been a cabal user. But I advise the community to not get excited too quickly with thinking cabal has caught up with everything that stack provides. Even modulo the automatic GHC installation, it’s still a fundamentally different UX that you can only achieve with cabal if you’re already a power user.

I think cabal needs to try harder, focus less on new features and more on UX and a clean specification.

I’m sure this will have someone bring up the money argument, but even given enough money, you still need to prioritize. What are the cabal maintainers priorities? I have no idea. Same for HLS.

7 Likes

Hi ktf. As one data point, yes I do recommend stack in many cases, especially for beginners and people struggling with ux or reproducibility; I do use stack and HLS (and VSC) successfully; and yes I guess I’m just bearing HLS-stack issues. My current setup is fairly stable, I know the workarounds, and I find it not too bad (much much better than not having HLS at all). I did spend a ton of time and frustration getting to this point.

More details: I’m usually in a medium-sized multi-package project (hledger) using HLS via the VS Code Haskell extension. Finding symbols, showing outlines, listing callers, showing errors usually works; when it stops working I do a Restart Haskell LSP server or Restart Extension Host and I’m usually back in business quickly. Or I kill other stack processes which might have been fighting with HLS’s, and do a stack clean --full. Or I remove the dist-newstyle directories left over from cabal experiments, which confuse HLS. Or (much more rarely these days) I do Reload Window, or quit and restart VSC, and/or study the Haskell Tasks pane carefully to see what’s going wrong.

Re “multi component support using stack”, yes people are working on that, see Component-based builds · Issue #6356 · commercialhaskell/stack · GitHub (it’s not easy). Do things fail to work across package/component boundaries ? In my experience, some do, some don’t; I think HLS includes various workarounds for this. It doesn’t cause me huge problems at the moment; perhaps I’m mostly working in one package/component at a time, and I Restart language server when moving to another one, or I just fall back on VSC’s search when HLS won’t find things.

I think both HLS and stack have a very difficult task (Haskell tool space has a long history and is by now super complicated), and of course both are underfunded/understaffed relative to the level of UX quality we wish for (HLS especially; I find stack’s quality generally very good).

The issues are well-documented

PS, maybe you could list the specific problems you’re hitting in your usage ? That would be useful.

[PPS above, I did not distinguish well between packages (like hledger-lib, hledger, and hledger-ui which each have their own .cabal file) and components (like the library, executable, and test suite within a package). In my typical usage I’m most often working with the single library components of 1-2 packages.]

3 Likes

Just another usage datapoint…

I switched wholeheartedly to Stack in 2014ish, switched begrudgingly back to cabal-install in 2018 when I started using Nix, started appreciating cabal-install’s improvements over the following years, and started using Stack again last year for the projects that use them.

In short, there are pain points in both tools, and your best bet is to stick to one and get real work done for a couple more years. If you keep using Haskell, you’ll eventually pick up the other tool, too, but you don’t need to rush it.

4 Likes

I use VS Code (code) with the Haskell extension (HLS-powered) when developing Stack with Stack, mostly on Windows 11. It took me a little while to realise that I had to run code in the Stack environment for HLS to work. That is, command:

stack exec -- code .

to open VS Code.

For the most part, that works fine for me. My experience is written up here: Contributor's guide - The Haskell Tool Stack ; and here: Stack and Visual Studio Code - The Haskell Tool Stack.

I don’t find HLS ‘very flakey’ with Stack, just the ordinary level of HLS niggles. In my own experience, HLS works fine*** with Stack’s default new project template. I would recommend Stack for newcomers to Haskell - they are a group of Stack users that is front of mind for me.

As I have posted elsewhere, both the HLS project and the Stack project are keen that HLS support Stack and that Stack can output the information that HLS needs to support Stack. The open issue on Stack’s repository has been mentioned above.

I don’t know that anyone is ‘being paid’ to develop Stack further. I’ve always assumed that all Stack development is done by volunteers.

EDIT: *** By ‘works fine’, I mean that stack build has to be run before VS Code is opened (otherwise HLS ‘hangs’). However, I think is a long-standing niggle with HLS.

3 Likes

That shouldn’t be required imo. It points to a bug either in hie-bios or the vscode-haskell extension itself.

@fendor

1 Like

To elaborate on that point: I found that in some circumstances (Template Haskell), HLS fell over if there was no GHC on the PATH. Running in the Stack environment ensures that GHC is on the PATH.

1 Like

That’s still a bug and shouldn’t be necessary :slight_smile:

3 Likes

I will see if it still applies with current HLS: my current behaviours reflect solutions to past experiences, and HLS may well have moved on in the interim.

EDIT: It still seems to be a current problem with GHCup-supplied HLS-2.9.0.1. Outside of the Stack environment (no ‘system’ GHC on PATH), HLS fails with:

[{
	"resource": "/D:/Users/mike/Code/GitHub/commercialhaskell/stack/src/Stack/Constants.hs",
	"owner": "Haskell (stack)",
	"severity": 8,
	"message": <see below>
	"source": "typecheck",
	"startLineNumber": 618,
	"startColumn": 3,
	"endLineNumber": 618,
	"endColumn": 76
}]

Message extracted from above:
• Exception when trying to run compile-time code:
    ghc: readCreateProcess: does not exist (No such file or directory)
  Code: (TH.runIO (readProcess \"ghc\" [\"--show-options\"] \"\")
           >>= TH.lift . lines)
• In the untyped splice:
    $(TH.runIO (readProcess \"ghc\" [\"--show-options\"] \"\") >>= TH.lift
        . lines)
1 Like

I definitely agree with this. And to be honest, in my dabbling with Cabal I’ve found that for everything other than HLS integration, I still prefer using Stack. But HLS integration is really important, especially for a new user.

For sure… for my own personal use, I’ve been using Stack and dealing with the workarounds. I think for non-beginners who understand the trade-offs, it’s fine just to dive in, knowing you’re going to have to futz around, figure out how to get past certain HLS/Stack annoyances.

For beginners, though, the experience is pretty bad. And the above issues, “well-documented” as they are for folks who have spent a bunch of time on these forums or searching through HLS github issues, are not at all obvious. They manifest as 1) seemingly inexplicable errors at the top of a file, or 2) files that inexplicably seem to be “behind” on your latest code changes. Again, for those with context, it’s not hard to do the dance of clearing caches, restarting servers, etc. For a beginner, that’s just “Haskell seems broken, what do I do”.

Speaking as a somewhat-recent Haskell beginner, I can say: I wanted a set of tools that integrated with each other in non-surprising ways :grinning_face_with_smiling_eyes:

If I could go back two years and give myself advice, it would be:

  1. "Use Stack, but here are a list of specific issues you’re going to run into if you use HLS (which, as a beginner, of course you’re going to use HLS), how those issues are going to manifest, and exactly what you need to do to fix them. Or, alternatively…
  2. Use Cabal. At least until you learn your way around enough to do otherwise."

If Stack is going to be recommended for new users, I think the Stack/HLS caveats should be called out loudly on the Haskell downloads page, the Stack documentation, and more loudly that they are already on the HLS documentation. People shouldn’t have to get to the point of starting a Stack project, getting elbows-deep into development, hitting issues, and navigating to a “troubleshooting” page to finally learn about these caveats.

Also, if there are specific steps that can always fix the issues, I feel like they should be written down and basically shouted from the rooftops. (Or even built into the tooling. The VS Code plugin could have a “Fix Stack by clearing caches, re-building, and restarting the server” button :grinning_face_with_smiling_eyes:.)

As it stands now, from the perspective of a beginner, it often feels like: “Well, here are some things you can try. Good luck…?”

4 Likes

Which project/team do you think should do that testing and documentation work, ideally ? Stack / HLS / Haskell Foundation / Everyone ?

Thanks for advocating for [new] users. I agree that identifying and documenting the current caveats and workarounds precisely will be a big help.

2 Likes

i use nix + cabal-install and my experience is that if i am not either trying to use a newer ghc than stackage-lts or a package with very few downloads, i tend to have 0 problems. Previously i used only cabal-install on archlinux and i don’t remember any issues besides the archlinux specific ones.

if stack is so flaky, i don’t know if hpack and a slightly better UX is worth it.

Ultimately, HLS supporting Stack better is a shared goal/shared problem of the HLS project and the Stack project.

However, the Stack project may look to the Cabal project, as Stack uses Cabal (the library) to build. That is, I understand that HLS would like to know from Stack what is passed to GHC to build a specific module but Stack does not know that directly; Stack passes commands to Cabal (the library) to build packages.

So, it seems to me, for Stack to know that information, Cabal (the library) has to tell Stack that information. Perhaps there is a Cabal command that does that, but I can’t see that it is documented at 5. Setup.hs Commands — Cabal 3.12.1.0 User's Guide.

(Cabal (the tool) has an --enable-build-info flag, but I can’t see that Cabal (the library) has something similar. EDIT: Correction: there is an configure --enable-build-info flag, documented only in-app.)

Stack does have a page of its online documentation on using Stack and VS Code (and its HLS-powered ‘Haskell’ extension): Stack and Visual Studio Code - The Haskell Tool Stack If people think there is something that could be usefully added to that page, please raise an issue at Stack’s repository.

HLS’s ‘needs a stack build to work’ problem is documented on that page as a ‘tip’. I had not appreciated that it had been identified in HLS’s documentation as a concrete problem.

1 Like

Of course! I think it’s easy (and totally natural) for experienced users with a lot of context to forget the mindset of a new user with zero context. That’s why I wanted to write this stuff down before I fully cross that threshold :smiley:

I think it’d have to be an overlapping effort. But take my suggestions with a grain of salt! I don’t fully understand the various teams, foundations, and companies involved. That said, here are some concrete changes that would have helped me as a new user:

  1. Clarify the toolchain options on the main Haskell downloads page. “Prefer” one build tool over the other by default, and clarify that the two tools are overlapping. (Right now, the implication is that both are “required”, by way of HLS being the only tool marked “optional”.)

  2. Be similarly opinionated on the main getting started page. This guide tells you to install both (probably good advice), but gives you no guidance one which to start with for your own projects (or why).

  3. The GHCup getting started guide is more successful in this way, I think. It picks cabal and gets you started with it. This guide should probably be linked from the main haskell.org page… it’s great!

  4. However the GHCup install page is less successful – to clarify the Stack/Cabal situation, it links to a gist which makes an attempt to be opinionated, but which makes no mention of the Stack/HLS caveats. It’s also filled with comments giving conflicting advice, which certainly comes across as confusing to a newcomer.

  5. The HLS troubleshooting page should probably contain concrete next steps for a user, e.g. “You have two options 1) Continue using Stack and do [these specific workarounds], or 2) Migrate your project to Cabal. Here are docs and/or tooling to accomplish that.” It would be helpful to clarify that these are not “temporary” problems, and that these issues have existed for years now.

  6. Mention the HLS/Stack issues in any/every place where the “Cabal vs. Stack” question is raised to new users. A user should never get to the point of stack new without being aware of these caveats, IMO. I think this should be loudly called out: 1) on the Haskell downloads page (if Stack is still recommended), 2) in the GHCup docs, 2) in the Stack docs, and 3) in the HLS docs (not just in the troubleshooting section). And, for better or worse, the issue manifests to users as an HLS problem (“HLS is broken in my tests but works in my main project”, e.g.), so I think HLS will have to bear some responsibility for documenting the potential solution(s).

I’d certainly be happy to file some relevant issues, open doc PRs, etc. I just don’t want to assume that my naive “here’s how I think things should be!” viewpoint is shared by everybody :grinning_face_with_smiling_eyes:

As for fixing the problem itself: from what I understand it’s a shared responsibility of Stack and HLS. Though from what I gather from this issue, the ball is somewhat in Stack’s court at the moment? But don’t quote me on that!

1 Like

HLS is ‘optional’, in the sense that you don’t really need it to develop Haskell projects - but it is very useful. Some people have argued in other discussions here that you don’t really need Stack or Cabal (the tool) either, to start out, but I think you need at least one of them once you move beyond evaluating expressions using GHCi.

The problem with an ‘opinionated’ getting started page, is … opinions differ. The respective strengths and weakness of Stack and Cabal (the tool) today for different purposes on different platforms are not easily summed up with ‘one-line advice’. If you are developing on Windows with Haskell packages that use C libraries, it can be useful that Stack supplies MSYS2, for example. If you want to use the Hpack package description format with Cabal (the tool), it requires a standalone hpack executable. (I say ‘today’ because existing guides can be out of date.)

GHCup is, I think, largely agnostic as between Stack and Cabal (the tool). Stack has its own quickstart guide and new-comer’s tutorial: The Haskell Tool Stack and Index - The Haskell Tool Stack. GHCup does not need to duplicate that.

I would be interested to know what are the issues in practice with using HLS with Stack. As I say, I use HLS with Stack to develop Stack, and it seems to work fine, mostly. However, I don’t use Cabal (the tool), so I don’t have a benchmark.

2 Likes

The confusing bit for me is that the page doesn’t make it clear that there’s a decision point there. The implication is that both Stack and Cabal are required. And the descriptions don’t clarify much: “tool for managing Haskell software” vs “program for developing Haskell projects”.

(And FWIW, as a newcomer to Haskell I was playing with individual .hs files with the help of HLS long before I started a real “project”. It’s a somewhat common pattern, I think.)

I don’t think these cases will often apply to Haskell beginners, though. As a beginner, I don’t want to pore over long comparisons of build tools that get into technical details far beyond my level – I just want to know how to get my toy program up and running.

I’m not suggesting that we as a community come out and say: “You must use Stack” or “You must use Cabal”. Rather, that we as a community should pick a path of least resistance for newcomers and document it well.

My naive summary is: HLS can’t seem to detect changes across different components in Stack projects. This can manifest in a number of vague, strange ways: obtuse HLS errors at the top of source files, files that seem to be “behind” changes in the rest of the project, or HLS simply being DOA in those files, for example. The workarounds are inconsistent and finicky, and not well-documented for new users.

EDIT: By the way, just to reiterate: I’m not trying to play favorites with Cabal here, or diss Stack. I personally strongly prefer the UX of Stack. It fits my needs perfectly, except for the HLS issues. But I do think those issues are enough to warrant questioning the idea recommending it to new users.

4 Likes