Last active
September 2, 2025 13:41
-
-
Save igor-ramazanov/7bd29ac9be57e14b9672204dba0e3075 to your computer and use it in GitHub Desktop.
Self-contained Haskell scripts with Nix optionally compiled as a static binary (using nix bundlers)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env -S nu --login --interactive | |
| # Can be written in any language. | |
| # The last positional argument will be automatically substituted to an absolute path to the script file. | |
| def tasks [] { | |
| { | |
| options: { | |
| case_sensitive: false | |
| completion_algorithm: substring | |
| sort: true | |
| } | |
| completions: [ | |
| "build", | |
| "bundle", | |
| "shell", | |
| "run", | |
| ] | |
| } | |
| } | |
| export def main [ | |
| --compiler: string | |
| --deps: list<string> | |
| --task: string@tasks | |
| --debug | |
| file:path | |
| ] { | |
| def log [msg: string] { if $debug { print $msg } } | |
| log $"compiler: ($compiler)" | |
| log $"deps: ($deps)" | |
| log $"task: ($task)" | |
| let basename = $file | path basename | |
| let name = $basename | str replace '.hs' '' | |
| let expr = $" | |
| let | |
| pkgs = import <nixpkgs> {}; | |
| dependencies = hpkgs: builtins.map \(dep: hpkgs.${dep}\) ($deps | to json --raw | str replace ',' ' ' --all); | |
| ghc = pkgs.haskell.packages.($compiler).ghcWithPackages dependencies; | |
| source = pkgs.writeText \"($basename)\" '' | |
| (open --raw Scotty.hs | lines | skip while {|line| ($line | str starts-with '#') or ($line | is-empty )} | str join "\n") | |
| ''; | |
| name = \"($name)\"; | |
| in | |
| pkgs.runCommandNoCCLocal \"($name)\" {pname = \"($name)\"; meta.mainProgram = \"($name)\"; nativeBuildInputs = [ghc];} '' | |
| mkdir -p ./.tmp $out/bin | |
| ghc \\ | |
| -outputdir ./.tmp/ \\ | |
| -hidir ./.tmp/ \\ | |
| -odir ./.tmp/ \\ | |
| -dumpdir ./.tmp/ \\ | |
| -tmpdir ./.tmp/ \\ | |
| -o ./.tmp/($name) \\ | |
| --make ${source} | |
| mv ./.tmp/($name) $out/bin/ | |
| rm -r ./.tmp/ | |
| '' | |
| " | |
| match $task { | |
| "build" => { | |
| let command = ["nix", "build", "--out-link", $name, "--impure", "--expr", $expr] | flatten | |
| log ($command | str join ' ') | |
| run-external ...($command) | |
| }, | |
| "bundle" => { | |
| let command = ["nix", "bundle", "--bundler", "github:DavHau/nix-portable/v012#zstd-max", "--out-link", ($name + "-bundled"), "--impure", "--expr", $expr] | flatten | |
| log ($command | str join ' ') | |
| run-external ...($command) | |
| }, | |
| "shell" => { | |
| # You can implement it the same manner as `build` and `bundle`. | |
| error make {msg: "'shell': not implemented"} | |
| }, | |
| "run" => { | |
| # You can implement it the same manner as `build` and `bundle`. | |
| error make {msg: "'run': not implemented"} | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!./haskell.nu --compiler ghc984 --deps [base scotty] --task bundle --debug | |
| {-# LANGUAGE OverloadedStrings #-} | |
| import Web.Scotty | |
| import Data.Monoid (mconcat) | |
| main = scotty 3000 $ do | |
| get "/:word" $ do | |
| beam <- param "word" | |
| html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"] |
Author
igor-ramazanov
commented
Aug 1, 2025
Author
Would be cool to rewrite the haskell.nu to use https://github.com/nh2/static-haskell-nix for building static binaries instead of https://github.com/DavHau/nix-portable/tree/main
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment