Nix - Trying out Haskell with less hassle
Tags: nix, haskell, functional
Published: 2020-06-10 01:07:53

---
title: Nix - Trying out Haskell with less hassle
published: true
description: 
tags: nix, haskell, functional
---

I heard you want to try out haskell but like me you hesitate because you don't know how to setup your enviroment for Haskell. Okay, hear me out. Nix can be the solution, I know you have to learn more. However, it's not that much. At least that's what I see. Just learn a little bit of nix now and learn as you go!

So if I convinced you to learn a little bit of nix. Go ahead and download it from their [website][nix].

Now, instead of worrying what system configuration you have to do, you just do this
```sh
mkdir my-project
nix-shell --pure -p ghc cabal-install --run "cabal init"
```
What's happening here is you're telling nix to go get `ghc`(compiler) and `cabal-install`(build tool), and run the command `cabal init`. This will generate a very small scaffold for a haskell project. Since we used the flag `--pure` it won't install anything global in your system.

Your `my-project` directory should look like this
```sh
my-project
|-- CHANGELOG.md
|-- Main.hs
|-- my-project.cabal
|-- Setup.hs
```
`Main.hs` should contain the `Hello World` program. This is also where you want to write your experiment haskell code.

Since you used `ghc` and `cabal` in a pure environment you won't find them when you try to execute `cabal` in the console. So you won't be able to run this project as is. What you can do is play with your haskell
project in a `nix-shell`. You can do this by first generating a `default.nix` file. This can be done by doing this command in your project directory

```sh
nix-shell --pure -p cabal2nix --run "cabal2nix ." > default.nix
```
This will generate the `default.nix` file and will contain
```nix
{ mkDerivation, base, stdenv }:
mkDerivation {
  pname = "my-project";
  version = "0.1.0.0";
  src = ./.;
  isLibrary = false;
  isExecutable = true;
  executableHaskellDepends = [ base ];
  license = "unknown";
  hydraPlatforms = stdenv.lib.platforms.none;
}
```
This file describes your project. It's like a function that takes in nix stuff.

For the last part, write the `shell.nix` file.
```sh
{ nixpkgs ? import <nixpkgs> {} }:

let
  inherit (nixpkgs) pkgs;
  inherit (pkgs) haskellPackages;

  project = haskellPackages.callPackage ./default.nix {};

in
pkgs.stdenv.mkDerivation {
  name = "my-project";
  buildInputs = project.env.nativeBuildInputs ++ [
    haskellPackages.cabal-install
  ];
}
```
When you perform `nix-shell --pure` in your project directory. It will go into a nix environment and you'll see your command prompt turn like this
```sh
[nix-shell:~/my-project]$
```

In this environment you'll have access to `cabal`. So you can build and run your project with `cabal new build` and `cabal new-run`.

If you want to expirement with a haskell package from [hackage][hackage] like the `text` package, you can add it to your `my-project.cabal` file, in the `build-depends` section.
```sh
cabal-version:       >=1.10
-- Initial package description 'my-project.cabal' generated by 'cabal
-- init'.  For further documentation, see
-- http://haskell.org/cabal/users-guide/

name:                my-project
version:             0.1.0.0
-- synopsis:
-- description:
-- bug-reports:
-- license:
license-file:        LICENSE
-- author:
-- maintainer:
-- copyright:
-- category:
build-type:          Simple
extra-source-files:  CHANGELOG.md

executable my-project
  main-is:             Main.hs
  -- other-modules:
  -- other-extensions:
  build-depends:       base >=4.13 && <4.14
                     , text
  -- hs-source-dirs:
  default-language:    Haskell2010
```

You should also add this to your `default.nix` file, so later on when you do decide to build your project with `nix-build` you don't have to chase around packages. I'll probably cover `nix-build` in another post.
```sh
{ mkDerivation, base, stdenv, text }:
mkDerivation {
  pname = "my-project";
  version = "0.1.0.0";
  src = ./.;
  isLibrary = false;
  isExecutable = true;
  executableHaskellDepends = [ base text ];
  license = "unknown";
  hydraPlatforms = stdenv.lib.platforms.none;
}
```

# References
[Getting Started Haskell Project with Nix - Soares Chen](https://maybevoid.com/posts/2019-01-27-getting-started-haskell-nix.html)

[Nix Shorts - Justin Woo](https://github.com/justinwoo/nix-shorts)

[nix]:https://nixos.org/download.html
[hackage]:https://hackage.haskell.org/