Skip to content

reflex-frp/nix-haskell

Repository files navigation

Nix-Haskell

A NixOS-style module system for building Haskell projects with haskell.nix. Provides declarative configuration for compilers, dependencies, cross-compilation, and development shells.

Note: Currently only the haskell.nix driver is implemented. Support for other drivers (e.g. nixpkgs haskellPackages, cabal2nix, reflex-platform) is planned.

Quick start

let nix-haskell = import ./deps/nix-haskell {};
in nix-haskell { src = ./.; }

The result is an attribute set:

{
  config       # Evaluated module configuration
  nixpkgs      # The nixpkgs package set
  haskell-nix  # haskell.nix project builder (with .override support)
  project      # Convenience aliases (project.haskell-nix)
  manual       # Documentation (manual.man, manual.md, manual.view)
}

Flake usage

{
  inputs.nix-haskell.url = "github:reflex-frp/nix-haskell";

  outputs = { nix-haskell, ... }:
    let lib = nix-haskell.lib.x86_64-linux;
        project = lib.nix-haskell ./project.nix;
    in {
      packages.x86_64-linux.default = project.haskell-nix.project;
    };
}

All attributes from default.nix are available as functions in lib.<system>:

lib.config module       # (nix-haskell module).config
lib.haskell-nix module  # (nix-haskell module).haskell-nix
lib.manual module       # (nix-haskell module).manual
# etc.

Module options

Project

Option Type Default Description
name nullOr str from src Project name
src path Project source directory
system str builtins.currentSystem Build system
compiler-nix-name str "ghc914" GHC compiler version

Cabal configuration

Option Type Default Description
source-repository-packages attrsOf (path | attrs) {} Local packages to include
extraCabalProject listOf lines [] Lines appended to cabal.project
index-state nullOr str null Hackage index snapshot
inputMap attrs {} URL to local source mappings
sha256map nullOr attrs null SHA256 map for cabal sources

source-repository-packages accepts either a path or an attrset with src and optional condition:

source-repository-packages = {
  reflex-dom = deps.reflex-dom + "/reflex-dom";
  obelisk-backend = {
    src = deps.obelisk + "/lib/backend";
    condition = "!arch(javascript)";
  };
};

Extra source files

extraSrcFiles = {
  library.extraSrcFiles = [ "static/style.css" ];
  exes.my-app.extraSrcFiles = [ "static/style.css" ];
};

Hackage overlays

Make custom packages visible to the cabal solver:

hackage-overlays = [
  {
    name = "my-package";
    version = "0.1.0";
    src = pkgs.fetchFromGitHub { ... };
  }
];

Overrides

haskell.nix module overrides. Lists are concatenated when composed (not replaced):

overrides = [
  ({ pkgs, lib, ... }: {
    enableDeadCodeElimination = true;
    packages = {
      obelisk-command.components.library.build-tools = with pkgs; [ ghcid jre openssh ];
      reflex-dom-core.components.tests.gc.buildable = lib.mkForce false;
    };
  })
];

Shell

shell = {
  crossPlatforms = ps: with ps; [ ghcjs wasi32 ];
  packages = ps: with ps; [ common frontend "backend" ];
  tools = { cabal = "latest"; };
  withHaddock = false;
  withHoogle = false;
};

When GHCJS is in crossPlatforms, Node.js is automatically added to buildInputs.

haskell.nix options

Pass options directly to the underlying haskell.nix project:

haskell-nix.options = {
  # haskell.nix specific configuration
};

Pins and dependency overrides

Override pinned dependencies at three levels:

{
  # Pin: path to source
  pins.haskell-nix = ./dep/your-haskell-nix;

  # Thunk: evaluated thunk source
  thunks.reflex-platform = thunkSource ./dep/your-reflex-platform;

  # Import: fully evaluated package
  importing.reflex-platform = import your-reflex-platform {};
}

Available pins: nixpkgs, haskell-nix, reflex-platform, nix-thunk.

Override

The haskell-nix.project output supports .override for composing additional configuration:

let project = (nix-haskell ./project.nix).haskell-nix.project;
in project.override (inputs: {
  overrides = [
    ({ pkgs, ... }: {
      packages.my-pkg.components.library.build-tools = [ pkgs.zlib ];
    })
  ];
})

Overrides use recursive merge — lists are concatenated, attrsets are merged recursively.

Full example

{ config, nix-haskell-patches, ... }:

let nix-thunk = config.importing.nix-thunk;
    deps = with nix-thunk; mapSubdirectories thunkSource ./deps;

in {
  imports = [
    "${nix-haskell-patches}/js/splitmix"
  ];

  name = "reflex-todomvc";
  src = ./.;
  compiler-nix-name = "ghc914";

  source-repository-packages = {
    reflex-dom = deps.reflex-dom + "/reflex-dom";
    reflex-dom-core = deps.reflex-dom + "/reflex-dom-core";
  };

  extraSrcFiles = {
    library.extraSrcFiles = [ "static/style.css" ];
    exes.reflex-todomvc.extraSrcFiles = [ "static/style.css" ];
  };

  shell = {
    crossPlatforms = ps: with ps; [ ghcjs wasi32 ];
    packages = ps: with ps; [ reflex-todomvc ];
    withHaddock = false;
    withHoogle = false;
  };
}

Modules documentation

nix run --no-write-lock-file github:reflex-frp/nix-haskell#manual-view

or docs/modules.md

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages