# Shell scripting with Haskell ## Problem Shell scripting is kinda broken: * Shell scripting languages differ or are interpreted with subtle differences * Higher level language concepts are typically missing Can Haskell be a good replacement for Bash—or similar languages—as a shell scripting language? ## Using GHCI for System Programing ### Setup 1. Install Haskell Stack ```bash brew install haskell-stack ``` 2. Install [turtle](http://hackage.haskell.org/package/turtle) using Stack ```bash stack install turtle ``` 3. Define functions to setup/init/extend Haskell shell and create an alias _hsh_ ```bash hsh_setup() { local hsh_home="${HOME}/.hsh" mkdir -p ${hsh_home} printf "[INFO] Creating hsh config" printf ':set -XOverloadedStrings\n:set prompt "λ> "\n:set +m\nimport Turtle\nimport Prelude hiding (FilePath)' > ${hsh_home}/.ghci printf "\n[INFO] hsh setup done" } hsh_extend() { local hsh_home="${HOME}/.hsh" \ command=${1} printf "\n[INFO] Creating function for command %-25s" "${command}" printf "\n%1\$s = \\\cl -> shell (\"%1\$s \" <> cl) empty\n%1\$s' = \\\cl -> shell (\"%1\$s \" <> cl)" ${command} >> ${hsh_home}/.ghci } hsh_init() ( local hsh_home="${HOME}/.hsh" hsh_setup while getopts "e:" option; do case ${option} in e) hsh_extend ${OPTARG} esac done cd ${hsh_home} stack ghci ) alias hsh=hsh_init ``` 4. Run Haskell Shell and have fun :raised_hands: ```bash $ hsh -e git [INFO] Creating hsh config [INFO] hsh setup done [INFO] Creating function for command git [INFO] Creating function for command latexmk [INFO] Creating function for command typora Note: No local targets specified, so a plain ghci will be started with no package hiding or package options. You are using snapshot: lts-17.2 If you want to use package hiding and options, then you can try one of the following: * If you want to start a different project configuration than /Users/main/.stack/global-project/stack.yaml, then you can use stack init to create a new stack.yaml for the packages in the current directory. * If you want to use the project configuration at /Users/main/.stack/global-project/stack.yaml, then you can add to its 'packages' field. Configuring GHCi with the following packages: GHCi, version 8.10.3: https://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /Users/main/.hsh/.ghci Loaded GHCi configuration from /private/var/folders/yz/b655kl71057db1lhwxhc0rt00000gs/T/haskell-stack-ghci/2a3bbd58/ghci-script ``` In the ghci REPL we can now use the Turtle library to do system programming similar to what we awould do in Bash. :rocket: ### The Good There are two very cool aspects of Haskell/GHCI that are being used here: 1. monads: most Turtle functions like `dir` and `echo` are monadic ```haskell λ> :t pwd pwd :: MonadIO io => io FilePath ``` and GHCI executes code within an IO monad; that means we can write in do-notation style and read/write from/to input/output ```haskell λ> dir <- pwd λ> dir FilePath "/Users/main/.hsh" ``` 2. overloaded strings: * E.g. `echo` has type `echo :: MonadIO io => Line -> io ()` (i.e. expects `Line` not `String`) which can however use the overloaded string literal syntax ```haskell λ> echo "Hi!" ``` 3. printing of return values: return of echo is something that is printable and GHCI therefore prints it nicely ```haskell λ> echo "Hi!" Hi! ``` The [Turtle tutorial on Hackage](https://hackage.haskell.org/package/turtle-1.5.21/docs/Turtle-Tutorial.html) has more examples. Be sure to check it out. ### The Bad * No Tab-Completion for commands/paths * No Syntax-Highlighting ## Bonus Round ### Launching GHCI Directly in Your Terminal Emulator In a terminal emulator like [iTerm](https://iterm2.com/), we can start _hsh_ in every new window/tab in order to get a complete Haskell based Shell feeling. ## Future Work [*ptghci*](https://github.com/litxio/ptghci) adds useful features like syntax highlighting and tab completion and might be a good extension. --- ## SOURCES * https://downloads.haskell.org/~ghc/7.6.3/docs/html/users_guide/ghci-dot-files.html