Welcome to haskell-scripting’s documentation!

Haskell is becoming more and more easy in terms of a language in which you can write small programs that usually are launched from command-line and do some helpful work. Unlike regular programming techniques, scripting is focused on “getting things done” in a fastest possible way, so usage of techniques like erroring out early and using exceptions is not considered a bad style.

This repository’s goal is to become a one-stop shop serving as a cookbook on scripting in Haskell, going from most simple and easy towards more complicated and framework-heavy patterns, capturing most common data formats and libraries used in scripting (“most common” metric was chosen arbitrary). PRs and Issues proposing improvements are welcome!

Prerequisites

  • install the stack tool
  • run stack setup to install GHC

Simple Scripts

Simplest script in haskell looks like this: [simple.hs](./simple.hs):

#!/usr/bin/env stack
-- stack --resolver=lts-12.7 script

main :: IO ()
main = do
  putStrLn "hello, scripting!"

Just mark this file as executable (via chmod +x ./simple_stdin_stdout.hs) and launch as usual:

$ ./simple_stdin_stdout.hs
hello, scripting!

You can compile your script to get an executable like this:

$ stack ghc --resolver=lts-12.7 ./simple_stdin_stdout.hs
Linking simple_stdin_stdout ...
$ ./simple_stdin_stdout
hello, scripting!

With a stack script shown above, you can use whatever packages are present in a snapshot without listing them out. For example: simple_with_dep.hs:

#!/usr/bin/env stack
-- stack --resolver=lts-12.7 script

import Database.Redis

main :: IO ()
main = do
  putStrLn "hello, scripting!"

If you want to use a non-snapshot dependency, you can use a stack runghc (or stack ghc) command with dependency packages being listed in a --package argument: simple_stdin_stdout_nonsnapshot_dep.hs:

#!/usr/bin/env stack
-- stack --resolver=lts-12.7 --package corenlp-parser script

import NLP.CoreNLP

main :: IO ()
main = do
  putStrLn "hello, scripting!"

Notes/Caveats:

  • TODO compiling with Wall/Werror and other flags
  • buffering (per-line? per-byte? need to set buffering mode)
  • best practice: upon reading/writing to stdin/stdout, usage of String is bad, better use Text, best – bytestrings (TODO: citation on encoding problems needed)

Indices and tables