proper tool for making development environments out of packages' build
environments: `shellFor`, a function exposed by every haskell package set. It
takes the following arguments and returns a derivation which is suitable as a
development environment inside `nix-shell`:
`packages`
: This argument is used to select the packages for which to build the
development environment. This should be a function which takes a haskell package
set and returns a list of packages. `shellFor` will pass the used package set to
this function and include all dependencies of the returned package in the build
environment. This means you can reuse Nix expressions of packages included in
nixpkgs, but also use local Nix expressions like this: `hpkgs: [
(hpkgs.callPackage ./my-project.nix { }) ]`.
`extraDependencies`
: Extra dependencies, in the form of cabal2nix build attributes. An example use
case is when you have Haskell scripts that use libraries that don't occur in
your packages' dependencies. Example: `hpkgs: {libraryHaskellDepends =
[ hpkgs.releaser ]}`. Defaults to `hpkgs: { }`.
`nativeBuildInputs`
: Expects a list of derivations to add as build tools to the build environment.
This is the place to add packages like `cabal-install`, `doctest` or `hlint`.
Defaults to `[]`.
`buildInputs`
: Expects a list of derivations to add as library dependencies, like `openssl`.
This is rarely necessary as the haskell package expressions usually track system
dependencies as well. Defaults to `[]`. (see also
[derivation dependencies](#haskell-derivation-deps))
`withHoogle`
: If this is true, `hoogle` will be added to `nativeBuildInputs`.
Additionally, its database will be populated with all included dependencies,
so you'll be able search through the documentation of your dependencies.
Defaults to `false`.
`genericBuilderArgsModifier`
: This argument accepts a function allowing you to modify the arguments passed
to `mkDerivation` in order to create the development environment. For example,
`args: { doCheck = false; }` would cause the environment to not include any test
dependencies. Defaults to `lib.id`.
`doBenchmark`
: This is a shortcut for enabling `doBenchmark` via `genericBuilderArgsModifier`.
Setting it to `true` will cause the development environment to include all
benchmark dependencies which would be excluded by default. Defaults to `false`.
One neat property of `shellFor` is that it allows you to work on multiple
packages using the same environment in conjunction with
[cabal.project files][cabal-project-files].
Say our example above depends on `distribution-nixpkgs` and we have a project
file set up for both, we can add the following `shell.nix` expression:
```nix
{
pkgs ? import <nixpkgs> { },
}:
pkgs.haskellPackages.shellFor {
packages = hpkgs: [
# reuse the nixpkgs for this package
hpkgs.distribution-nixpkgs
# call our generated Nix expression manually
(hpkgs.callPackage ./my-project/my-project.nix { })
];
# development tools we use
nativeBuildInputs = [
pkgs.cabal-install
pkgs.haskellPackages.doctest
pkgs.cabal2nix
];
# Extra arguments are added to mkDerivation's arguments as-is.
# Since it adds all passed arguments to the shell environment,
# we can use this to set the environment variable the `Paths_`
# module of distribution-nixpkgs uses to search for bundled
# files.
# See also: https://cabal.readthedocs.io/en/latest/cabal-package.html#accessing-data-files-from-package-code
distribution_nixpkgs_datadir = toString ./distribution-nixpkgs;
}
```
<!-- TODO(@sternenseemann): deps are not included if not selected -->
### haskell-language-server {#haskell-language-server}
To use HLS in short: Install `pkgs.haskell-language-server` e.g. in
`nativeBuildInputs` in `shellFor` and use the `haskell-language-server-wrapper`
command to run it. See the [HLS user guide] on how to configure your text
editor to use HLS and how to test your setup.
HLS needs to be compiled with the GHC version of the project you use it