2 years ago

#32930

test-img

nicolas

running a program in haskell with just nix installed

If I have nix installed, I can run pretty much any program, without having it "installed".

  • For instance a javascript program require node
//in file  helloworld.js
const http = require('http'); // Loads the http module
http.createServer((request, response) => {
    response.writeHead(200, {
        'Content-Type': 'text/plain'
    });
    response.write('Hello, World!\n');
    response.end();
}).listen(1337);

and I can directly run it with

$(nix-build -E "with import <nixpkgs> { };nodejs")/bin/node helloworld.js
  • For simple haskell, I can likewise both summon a haskell environment, and have it run directly with a bash script :
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p "haskellPackages.ghcWithPackages(p: with p; [type-level-sets])"
#! nix-shell -I nixpkgs=channel:nixos-21.11

-- courtesy jyrimatti https://gist.github.com/jyrimatti/bd139e91ed257d37bc57c08ac505fc3f

{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeApplications #-}

module Main where

import Data.Type.Set (Set(..), Proxy(..))

class Get a s where
 get :: Set s -> a

instance {-# OVERLAPS #-} Get a (a ': s) where
           get (Ext a _) = a

instance {-# OVERLAPPABLE #-} Get a s => Get a (b ': s) where
          get (Ext _ xs) = get xs

main :: IO ()
main = do
let lst = Ext "hello" $ Ext 10 $ Empty
putStrLn $ show $ get @String lst

However, say my program is more complicated, like the webserver example, and I want to target a particular package set. now all my dependencies are picked from that vetted set of packages which are known to be compatible with each others.

With stack installed, this is easy :

#!/usr/bin/env stack
-- stack --resolver lts-18.21 script

-- this script makes use of the http-client library, which is in stackage
{-# LANGUAGE OverloadedStrings #-}

import qualified Data.ByteString.Lazy.Char8 as L8
import Network.HTTP.Simple

-- An equivalent pure haskell file can also be run as
-- stack runghc --package http-conduit -- http.hs

main :: IO ()
main = do
  response <- httpLBS "http://httpbin.org/get"

  putStrLn $
    "The status code was: "
      ++ show (getResponseStatusCode response)
  print $ getResponseHeader "Content-Type" response
  L8.putStrLn $ getResponseBody response

Is there an equivalent for nix which would make it simple to (reliably !) launch some haskell program, along with its dependencies, without anything special installed apart from nix ?

I imagine something like :

#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p "stackage.lts-18.21"
#! nix-shell -I nixpkgs=channel:nixos-21.11

-- this script makes use of the http-client library, which is in stackage
{-# LANGUAGE OverloadedStrings #-}

import qualified Data.ByteString.Lazy.Char8 as L8
import Network.HTTP.Simple

-- An equivalent pure haskell file can also be run as
-- stack runghc --package http-conduit -- http.hs

main :: IO ()
main = do
  response <- httpLBS "http://httpbin.org/get"

  putStrLn $
    "The status code was: "
      ++ show (getResponseStatusCode response)
  print $ getResponseHeader "Content-Type" response
  L8.putStrLn $ getResponseBody response

bash

haskell

nix

0 Answers

Your Answer

Accepted video resources