Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Running a haskell script without GHC using nix

Updated version can be found on my website.

Running a haskell script without GHC

Given the following haskell script generate-random-samples.hs that requires mwc-random ...

{-# LANGUAGE ScopedTypeVariables #-}

import System.Random.MWC
import Data.Vector.Unboxed
import Control.Monad.ST

main = do
  vs <- withSystemRandom $
        \(gen::GenST s) -> uniformVector gen 20 :: ST s (Vector Int)
  print vs

... how do you run it without having to globally install the package or having to build a whole cabal project ?


One of the simplest approaches using nix is the following:

$ nix-shell --packages 'haskellPackages.ghcWithHoogle (pkgs: with pkgs; [ mwc-random ])'
nix-shell> runghc generate-random-samples.hs

In order to reuse the command so other people can run the script, you can add the following shell.nix:

{ compiler ? "ghc881" }:
let

  pkgs = import (builtins.fetchGit {
    url = "https://github.com/NixOS/nixpkgs.git";
    rev = "890440b0273caab258b38c0873c3fe758318bb4f";
    ref = "master";
  }) {};

  ghc = pkgs.haskell.packages.${compiler}.ghcWithPackages (ps: with ps; [
          mwc-random
        ]);

in

pkgs.stdenv.mkDerivation {
  name = "ghc-env";
  buildInputs = [ ghc pkgs.cabal-install ];
  shellHook = "eval $(egrep ^export ${ghc}/bin/ghc)";
}

So now you only need to call $ nix-shell to enter into a pure shell with a specific GHC version that includes all your dependencies:

$ nix-shell
nix-shell> runghc generate-random-samples.hs

The only issue is that you must be aware of how nix work in order to be able to run the script.

But these could be solved using bash shebangs in your haskell script:

#!/usr/bin/env nix-shell
#!nix-shell -i runghc
{-# LANGUAGE ScopedTypeVariables #-}

import System.Random.MWC
import Data.Vector.Unboxed
import Control.Monad.ST

main = do
  vs <- withSystemRandom $
        \(gen::GenST s) -> uniformVector gen 20 :: ST s (Vector Int)
  print vs

So now, you can run your haskell script in an environment without ghc:

./generate-random-samples.hs
[6052359640365008112,3693984866634705670,6521947999724514858,640433474764908030,-4262896110044960033,-1795671341099353119,-2220462704949887998,-248182841640258167,709016591698961687,-3622504171575206589,5987258113070378446,-159251391303273987,-8449937247808153766,6165509553180365166,-8199532339362621783,-9187765480154042269,-2389922548196927048,-4842141643835297495,-1106748185069026877,826927505518387091]
@monadplus

This comment has been minimized.

Copy link
Owner Author

@monadplus monadplus commented Jun 8, 2020

You can also inline everything by replacing the header by this one

!/usr/bin/env nix-shell
! nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ mwc-random ])" -i runghc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment