Home Explore Blog Models CI



nixpkgs

10th chunk of `doc/languages-frameworks/haskell.section.md`
7c1eeb9b6dcec112a7c826826ce3dca818d216035181b4820000000100000fd3
}:

# use the nixpkgs default haskell package set
pkgs.haskellPackages.callPackage ./my-project.nix { }
```

Using `nix-build default.nix` we can now build our project, but we can also
enter a shell with all the package's dependencies available using `nix-shell
-A env default.nix`. If you have `cabal-install` installed globally, it'll work
inside the shell as expected.

### shellFor {#haskell-shellFor}

Having to install tools globally is obviously not great, especially if you want
to provide a batteries-included `shell.nix` with your project. Luckily there's a
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

Title: Nix `shellFor`: Declarative Haskell Development Environments
Summary
This document introduces `shellFor`, a declarative Nix function for creating Haskell development environments, removing the need for global tools. Exposed by any Haskell package set, it returns a `nix-shell` derivation, customizable via arguments: `packages` (selects packages for dependency inclusion), `extraDependencies` (additional Haskell libraries), `nativeBuildInputs` (development tools like `cabal-install`, `doctest`, `hlint`), `buildInputs` (non-Haskell system dependencies), `withHoogle` (includes Hoogle with populated database), `genericBuilderArgsModifier` (`mkDerivation` adjustments), and `doBenchmark` (to include benchmark dependencies). The text also shows `shellFor`'s use for multi-package projects (e.g., `cabal.project` files) through an example `shell.nix` integrating Nixpkgs, local projects, and essential development tools.