[Haskell-cafe] technical thoughts on stack

Michael Snoyman michael at snoyman.com
Mon Sep 26 13:40:15 UTC 2016

On Mon, Sep 26, 2016 at 4:23 PM, Richard Eisenberg <rae at cs.brynmawr.edu>

> Thanks, Michael, for repeating this here. (I'm not on Twitter, as you may
> have figured out.)
> So, as I understand it, I could use the procedure below to install a
> "system GHC", which could then be filled out with libraries by either
> `cabal install xxx` or `stack install xxx`.
> If this is indeed the case, I will expect to recommend stack to my
> students next semester, along with instructions of how to modify their
> PATHs. I'd also be happy to reconsider recommending stack as the one option
> on a downloads page, if we include the PATH updating instructions.
This is _almost_ the case. When you use `stack install xxx` (or, for that
matter, `cabal install xxx` inside a sandbox), no packages will be
registered in the default user package database. Without modifying
`GHC_PACKAGE_PATH`, those packages will not be available from a straight
`runghc`. By contrast, `stack exec -- runghc` _will_ have access because it
sets the `GHC_PACKAGE_PATH` env var.

One possibility to overcome this is to just modify your ~/.bashrc to say:

export PATH=$(stack path --bin-path)
export GHC_PACKAGE_PATH=$(stack path --ghc-package-path)

This is probably a fairly safe move overall, but it's not well tested (or,
at least, _I_ haven't tested it well). Then you'd be able to `stack build
some-library` and have it available. Or, leave off GHC_PACKAGE_PATH, use a
`cabal install some-library` without a sandbox, and get the same result.
(Typical downsides of lack of sandboxes would apply of course.)

> With regard to `stack exec`: If I modify my PATH to allow direct calls to
> ghc(i) and then create a project with a stack.yaml, won't `stack exec` use
> the local settings, etc., when I'm in a subdirectory of the project? At the
> bottom of your email, it sounds like you're recommending not modifying my
> PATH, instead always using `stack exec` for a better experience. But it
> seems to me that modifying my path allows me to skip the `stack exec`
> outside of projects while still retaining the nice behavior inside of
> projects, a net win to my eyes. (Your opinion on this may differ, of
> course.) Is there something I'm missing here?
It's really a matter of what you consider best, thus my referral to
established workflows. If you use the PATH modification trick, and have a
global configuration targeting GHC 8.0.1, and then go inside a directory
that using GHC 7.10.3:

* `stack exec -- ghc` will use GHC 7.10.3
* `ghc` will use GHC 8.0.1

Honestly, this somewhat gets to a point of trying to read the user's mind
about what the anticipated behavior is. Personally, I've come to expect and
enjoy the behavior of respecting the local settings, though there are
certainly times when it's _not_ what I want. So take my recommendation to
stick with `stack exec --` with a large grain of salt; as long as you
understand that `stack exec ghc` and `ghc` in a given directory may behave
differently, the PATH trick can work.

And especially for teaching purposes, I can imagine the situation of
multiple GHC versions to be a much smaller concern.

> (Sidenote: You used `stack build` where I expected `stack install` in your
> gist. I understand that the latter copies executables somewhere and the
> former does not, but then it seems that the binaries are available in
> `stack path --bin-path`, so I'm a bit confused.)
Every project has a .stack-work directory, and (somewhere) inside of that
is a /bin/ directory, where `stack build` automatically copies executables
to. (A similar directory exists for each snapshot.) When you use `stack
exec`, it adds these /bin/ directories to your PATH, so that you can easily
run locally built executables. This is useful in many cases, but perhaps
the most important is when you have an executable (like intero or ghc-mod)
which is built against a specific GHC version: you're guaranteed to get the
appropriate binary instead of whatever the last one to be installed happens
to be.

`stack install` by contrast copies this binaries out of those /bin/
directories and into ~/.local/bin (and somewhere else on Windows, I don't
remember where offhand). This is a semi-standard directory for installing
user built tools. This makes a lot of sense for tools like pandoc,
stylish-haskell, hindent, etc: tools you'd want to use regardless of GHC
version, and possibly when not working on Haskell code at all.

> Thanks again for your input here!
> Richard
Pleasure, thanks for starting the conversation :)


> -=-=-=-=-=-=-=-=-=-=-
> Richard A. Eisenberg
> Asst. Prof. of Computer Science
> Bryn Mawr College
> Bryn Mawr, PA, USA
> cs.brynmawr.edu/~rae
> On Sep 26, 2016, at 6:32 AM, Michael Snoyman <michael at snoyman.com> wrote:
> I just realized that I had shared this answer on Twitter, but not on this
> mailing list.
> For those wanting to have direct access to GHC and other such tools,
> without needing to prefix calls with `stack exec -- `, the following added
> to your ~/.bashrc (or equivalent) will do the trick:
>     export PATH=`stack path --bin-path`
> This can go as far as providing a means of using cabal-install, for
> example:
> https://gist.github.com/snoyberg/959a2ade4287de6129910eeabec1d9d2
> For those without an established workflow, or open to experimenting with
> new workflows, I'd still recommend sticking with `stack exec -- ` in
> general, since it composes nicely with projects, letting you automatically
> switch to different GHC versions and package sets. But this is certainly
> another option to consider.
> On Tue, Sep 13, 2016 at 9:58 PM, Richard Eisenberg <rae at cs.brynmawr.edu>
> wrote:
>> I’ve watched the recent back-and-forth about stack with quite a bit of
>> interest (as many of us have). The discussion inspired me to take another
>> look at stack. Here are the results of that foray.
>> First, a disclosure: While I have appreciated the emergence of a new
>> build tool for Haskell, I have never much liked stack. One of my chief
>> goals in taking another look is to understand better why I do not like it.
>> My task: Set up a Haskell environment on a new machine (a Mac). This
>> machine has no Haskell infrastructure on it.
>> My approach:
>> 1. `brew install haskell-stack`. Success.
>> At this point, I do not have a Haskell project I wish to build. Instead,
>> I really just want the ability to run Haskell expressions in GHCi. So I
>> skip `stack new` and go straight to
>> 2. `stack setup`. This succeeds, but prints out some interesting messages
>> along the way, including
>> > Did not find .cabal file for servant-yaml- with Git SHA of
>> 71c0a55d0a877954d9590e285c0eb861ace2d8cc
>> > Right Nothing
>> At the end, I am helpfully told
>> > To use this GHC and packages outside of a project, consider using:
>> > stack ghc, stack ghci, stack runghc, or stack exec
>> >
>> So I then
>> 3. `stack ghci`. My computer’s first reaction is to say
>> > Run from outside a project, using implicit global project config
>> > Using resolver: lts-6.17 from implicit global project's config file:
>> /home/rae/.stack/global-project/stack.yaml
>> > Error parsing targets: The specified targets matched no packages.
>> > Perhaps you need to run 'stack init'?
>> > Warning: build failed, but optimistically launching GHCi anyway
>> >
>> which doesn’t make me feel all that comfortable, but then I am indeed
>> delivered to the GHCi prompt, which works as expected.
>> Done with GHCi, I quit. I then want to double-check which version of GHC
>> I got, so I
>> 4. `stack ghc --version`. This command reports
>> > Invalid option `--version’
>> Grumble. It seems I can’t interact with GHC directly.
>> ————
>> At this point, I am reminded why I dislike stack:
>> **It’s optimized for a different workflow than I use.**
>> And I think this fact (repeated by others’ experiences) is why a segment
>> of our community has not celebrated stack as much as other segments have.
>> We all have different workflows.
>> From what I understand about it, stack is great for a project-based
>> workflow. In this workflow, you are working on a Haskell project. You are
>> happy to specify settings in .cabal and stack.yaml files. And you really
>> want your build to work in the future and on other machines.
>> In my experience, stack is not great with a compiler-based workflow. In
>> this workflow, you aren’t quite as organized perhaps and do not have all
>> your settings written. You also want the ability just to compile a file
>> without changing any configurations. You want to be able to start GHCi with
>> a nice set of libraries with which to experiment.
>> I definitely like a compiler-based workflow. I’m sure that many of you
>> prefer a project-based workflow.
>> The great news here is that we have a choice: use stack for a
>> project-based workflow, and don’t use it when you want a compiler-based
>> workflow. No one needs to convince others about personal preferences.
>> But there is one nagging issue: what do we suggest to newcomers? The
>> downloads page right now is not serving us well. (I was legitimately
>> scratching my head at first trying to figure out how to provision a new
>> computer.) Sadly, I don’t see a good option presenting itself. Both
>> potential approaches (The Haskell Toolchain vs. stack) have (in my opinion)
>> serious shortcomings.
>> A. The Haskell Toolchain (that is, what’s currently called the Haskell
>> Platform Minimal) does appear to lack a “here’s what you do first”
>> tutorial. Forgive me if I’ve missed it. It’s also right now quite hard to
>> discover — you have to choose the oft-maligned Haskell Platform link before
>> you are told that there is a minimal variant.
>> B. stack sets up GHC in a way that either 1) requires a project-based
>> workflow with a stack.yaml file or 2) issues a bunch of somewhat-scary
>> warnings every time GHC is invoked outside of a project. Furthermore, stack
>> prohibits direct interaction with GHC (as in `ghc --version`).
>> There’s more good news here! Both of these problems are really easy to
>> fix.
>> To fix (A), someone just has to write the tutorial.
>> To fix (B), stack just needs a new option so that `stack setup` installs
>> a system GHC. Perhaps it would even be sufficient for `stack setup` to
>> clearly tell the user where ghc is installed and what to add to their PATH.
>> I also think, if readers agree with my conclusions about workflows, we
>> should consider writing up criteria that potential users should consider
>> when choosing what workflow to start with. We’ll need to have a tighter
>> recommendation for those with no experience programming, but most
>> developers should be able to recognize what workflow they prefer and choose
>> accordingly.
>> Of course, there’s a bit of bad news: If both (A) and (B) are fixed, then
>> we’ll really be in a quandary about which installation procedure to put
>> first. Perhaps we should incentivize fixing (A) and (B) by saying whichever
>> one happens first gets to be featured first on the page? :)
>> So: Does my characterization of workflows resonate? Have I perhaps
>> identified part of the burning black heart of the reason behind the vitriol
>> of late? Should we fix (A) and (B)?
>> I’m looking forward to hearing your thoughts.
>> Richard
>> -=-=-=-=-=-=-=-=-=-=-
>> Richard A. Eisenberg
>> Asst. Prof. of Computer Science
>> Bryn Mawr College
>> Bryn Mawr, PA, USA
>> cs.brynmawr.edu/~rae
>> _______________________________________________
>> Haskell-Cafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>> Only members subscribed via the mailman list are allowed to post.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20160926/16630814/attachment.html>

More information about the Haskell-Cafe mailing list