Local install packages with Stack for use with runhaskell - haskell

I am developing many small haskell programs that I indent to use as script files. My ideal use-case is to stack runhaskell one-of-the-scripts.hs to run them.
Some of the files use dependencies on packages in hackage, such as regex-posix. Therefore I get an error message saying
Could not find module `Text.Regex.Posix'
Use -v to see a list of the files searched for.
|
2 | import Text.Regex.Posix
| ^^^^^^^^^^^^^^^^^^^^^^^
I have considered two options:
Use a cabal package and specify dependencies therein. I don't like this solution since it (by what I understand) is used in a workflow where I always compile my code. I would like to use stack runhaskell instead!
Ditch stack and use cabal straight up instead, as suggested in an answer to a similar question here on SO: https://stackoverflow.com/a/13485987/4050510. I dont like this, since I would like to have all my dependencies listed in some file explicitly.
What is the simplest way to install packages from hackage locally, and have then available for stack runhaskell ?

You probably want to use the script interpreter. Sorry over concision on the answer but I'm on my phone. Here's the docs for it: https://docs.haskellstack.org/en/stable/GUIDE/#script-interpreter
You could also just do "stack build regex-posix", and then the package will be available to runhaskell. However, this is more error prone because no package hiding is used so it's trickier to tell what the script actually depends on

Related

Problem with loading module ‘Distribution.Simple’

I was trying to build one new project in Haskell (GHC version 8.10.4, stack version 2.7.3, cabal version 3.6.2.0) using stack, but at the time of running the command stack setup I (surprisingly) got the following error:
Setup.hs:2:1: error:
Could not load module ‘Distribution.Simple’
It is a member of the hidden package ‘Cabal-3.2.1.0’.
You can run ‘:set -package Cabal’ to expose it.
(Note: this unloads all the modules in the current scope.)
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
2 | import Distribution.Simple
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
Also, it is worth noting that I was trying to look for different solutions on the Internet, but didn't find the working one for me. The general idea was to explicitly add Cabal into the package.yaml file here:
library:
source-dirs: src
dependencies:
- Cabal
But that didn't save my situation. I was able to build the project without that step (well, just skipped that part), but I was interested to solve the issue.
Moreover, when I was trying to build Haskell package timeit (as an example, using the command line), there was the same error at the time of executing
runhaskell Setup.hs configure.
Interestingly, I didn't have this problem before (probably, it appeared after I updated GHC).
Does anybody know any ways of how to deal with such issue? Is there any way probably to reinstall the GHC, or cabal, or stack (if it helps)? Would be glad to see any comments and solutions.
Instead of deleting the
~/.ghc/*/environments/default
file, just add the Cabal package to it, including version number, which you can find if you run the command:
ghc-pkg list
I had the same issue.
Deleting the files
~/.ghc/*/environments/default
(or the whole folder .ghc) solved the stack setup problem.
It seems that they were somehow interacting with stack's operations.

Find the package a Haskell module belongs to

I'm new to Haskell stack and wondering how to find out the name of the package that contains a particular module.
Currently, I want to use Data.Tuple.Extra(fst3) ( https://hackage.haskell.org/package/extra-1.7.9/docs/Data-Tuple-Extra.html ) and want to know what I should write below
$ stack install ????
I've already installed the tuple package, which, however, doesn't seem to include the Extra part.
All the Internet resources about the installation of a package I've found so far say something along the lines of "To use Blahblah.Anything.Something, you need to install the foofoo package" . . . How can one know? I searched Stackage but it shows only the documentation of Data.Tuple.Extra and I still fail to find the name of the package.
Edit: As K.A.Buhr notes in her/his answer, stack install is the wrong command for the above case. Use stack build instead.
When browsing package documentation in Hackage, the top-left portion of the page header will always give the package, version number, and description. On the page you link, it's here:
You can also use the "Contents" link in the top-right to go to the main page for the extra package, which gives its full list of modules, licensing, links to the package home page and bug tracker, and so on.
As a side note, stack install extra is technically the wrong command to "install" this package. If you want to make the extra package available for use within the Stack global project, the correct command is stack build extra. If you want to use extra within a stack project, then you want to add extra to the dependencies in your package's xxx.cabal or package.yaml file instead and run stack build (no arguments) to build and install it for use in your project.
In contrast, the stack install command is equivalent to stack build --copy-bins which copies any executables in the package to ~/.local/bin so they'll be in your path. See the Stack docs. It's intended to be used for installing programs written in Haskell that are distributed via Stack, so you can do stack install hlint to install the hlint linter, for example.
In this case, because the extra package has no executables, stack install extra and stack build extra will do the same thing, but it's better to get into the habit of using stack build when you aren't intending to install any package binaries, to avoid surprises.

Recommended approach to use Stack as global package manager

I would like to install some Haskell libraries globally, for example hindent which is used by my editor's Haskell integration. What is the recommended way to do this?
I thought that stack install hindent was the correct way to do this. However, then I wanted to update my packages and found that there was no way to do this. According to the GitHub issue report I found,
stack is concerned with managing a local build sandbox for a project. It isn't intended to be a global package manager.
There appear to be workarounds such as maintaining a dummy project with artificial dependencies on the packages I would like installed. This sounds like a terrible hack, and I have been unable to find any official documentation on what approach should actually be taken.
Installing Haskell packages using my system package manager (Homebrew) is not an option since they are not packaged.
I would have opened an issue report against Stack, however the contribution guidelines requested that I instead ask a question here under the haskell-stack tag.
Well, stack install in any project will install to ~/.local/bin therefore making whatever executable you install be globally accessible.
The global project is used when running stack without a project, it is located in ~/.stack/global-project/stack.yaml.
If you want all of your globally accessible tools to have the same dependencies (perhaps to ensure that the ghc version matches or something), then you could make a project intended to build all of these tools. It's up to you whether or not it is the "global project" - there's not much special about it, it's just a default if you run stack and aren't in a project.
In order to record "what haskell executables do I want installed globally", you might consider creating a shell file like
#!/bin/sh
stack install hindent
And then running this whenever you change the versions of the installed tools.
Also, for tools like intero that need to match the ghc version, you can do stack install --copy-compiler-tool intero, and it will be available on the PATH when stack is used with that ghc version.

Installing local package with Stack

Is it possible to install package from sources with something similar to stack build package-name? (latter works with packages on Stackage, but not with custom ones)
Um, stack build (within the source directory)?
Stack doesn't really have a notion of installing libraries though, it only installs executables. To “install” locally-sourced packages, you need to specify what for you want them installed: add them as dependencies to another project, via a location: field in the packages: field in that project's stack.yaml file.
That's arguably sensible since, one might say, there's nothing you can do with an installed library except invoking it in another Haskell project (or in a REPL, which you can get with stack ghci). I personally don't hold with that though, I like actually being able to say install that library now. Which is one of the reasons I have always stuck to good old cabal-install rather than Stack. With that, you can just
cabal install
from within the source directory.
Cabal-install has often been criticised: its local installs can easily get out of sync and then you have weird dependency conflicts and need to rebuild lots of stuff. I never found this that much of a problem, and anyway this has been adressed in recent Cabal through Nix-style builds, which never produce conflicts.

cabal build-depends: how to find?

How can I find out what needs to go into the module.cabal build-depends? I mean, some modules may already be part of the Haskell platform whilst others may not? How to I find out/know what I must write here so that the module I offer will install with cabal on the majority of Haskell installations "out there"?
My situation is that I have it working on my systems, but cannot remember for what import I actually had to install an other module and what was part of the Haskell Platform that I use. How do I now best find the way from my situation to a cabal installable package?
If you use Cabal to build your project, it will only look at the modules listed in the .cabal file, even if you have other modules installed locally.
So all you have to do is run it as is (with nothing in the depends declaration) and it will give you an error for each module you need to specify. I think the error even tells you the name of the package.

Resources