7 Useful Tools Written in Haskell
Tags: haskell, functional, programming
Published: 2021-10-18 14:18:22

Author: Nikolay Rulev

## Introduction

Haskell is a pure functional general-purpose programming language with static typing and lazy evaluation. It was created in 1990 and was named after Haskell Curry. At present, the GHC compiler is its main implementation.

Here at Typeable we like this language very much and use it as our [main language for software development](https://typeable.io/blog/2021-05-11-languages-choice.html). Though Haskell is already quite widely used in the industry, it’s still sometimes believed to be an "academical" language used exclusively for scientific purposes. In this post, I’d like to tell you about several rather popular Haskell tools which may be of use to you.

## Useful tools written in Haskell

### 1. Xmonad

[Xmonad](https://xmonad.org/) is a tile window manager for X Window System, written in Haskell. The distinctive feature of this tile manager is that it’s configured in Haskell, too, which allows us to use all features of the language. Thus, while configuring the window manager, you can add weather forecast data, measure the system condition, etc.

Here is an example of configured system ([by erikbackman](https://github.com/erikbackman/nixos-config)):
![Xmonad screenshot by erikbackman](https://typeable.io/images/hasktools/xmonad.jpg)

A config example (only a part is shown, not the entire config):

```haskell
main :: IO ()
main = xmonad . dynamicProjects (projects apps) . ewmh . docks . cfg =<< polybar
  where
    cfg dbus =
      def
        { manageHook = App.manageApps <+> manageSpawn,
          logHook = dynamicLogWithPP (polybarHook dbus),
          startupHook = myStartupHook,
          terminal = fromMaybe "xterm" $ App.terminal apps,
          modMask = mod4Mask,
          borderWidth = 1,
          keys = keybinds . KeybindConfig apps,
          handleEventHook = handleEventHook def <+>
            fullscreenEventHook,
          layoutHook = myLayouts,
          focusedBorderColor = "#bd93f9",
          normalBorderColor = "#434C5E",
          workspaces = myWS
        }

    apps =
      defaultAppConfig
        { App.terminal = Just "kitty",
          App.launcher = Just "rofi -matching fuzzy -show drun -modi drun,run -show-icons",
          App.mailClient = Just "claws-mail"
        }

    myStartupHook :: X ()
    myStartupHook = do
      setDefaultCursor xC_left_ptr
```

You can find further information on the  [xmonad](https://xmonad.org/TUTORIAL.html) website.

### 2. ShellCheck

ShellCheck is a utility used to analyze bash scripts. It allows novices to fish out common errors when they just start learning this scripting language and helps more advanced users not to miss small bugs in large and complex scripts. The project is being constantly expanded and its large community is adding new rules. You can view the ShellCheck and try it out at [its home page](https://www.shellcheck.net/).

Let’s use the following script by way of example (try to find the errors in it without looking into the ShellCheck result):

```sh
#!/bin/bash
## Example: ShellCheck can detect some
## higher level semantic problems

while getopts "nf:" param
do
    case "$param" in
        f) file="$OPTARG" ;;
        v) set -x ;;
    esac
done

case "$file" in
    *.gz) gzip -d "$file" ;;
    *.zip) unzip "$file" ;;
    *.tar.gz) tar xzf "$file" ;;
    *) echo "Unknown filetype" ;;
esac

if [[ "$$(uname)" == "Linux" ]]
then
    echo "Using Linux"
fi
```

It’s very easy to check the file: `shellcheck example.bash`.

As the result, we’ll be informed about all potential errors in the script:

![ShecllCheck finds even higher-level semantic problems](https://typeable.io/images/hasktools/shellcheck.png)

### 3. PureScript

Haskell was used to develop several popular compiled functional languages for the frontend development which are eventually [transpiled into JavaScript](https://typeable.io/blog/2021-04-05-js-transpilation.html). Today we’re going to talk about PureScript. This language has a strict type system supporting algebraic data types, HKT (Higher-Kinded Types), and type classes with functional dependencies. It also supports several necessary and handy features such as FFI (Foreign Function Interface) with JS, and the resulting JS looks very much readable. The language has already acquired its own ecosystem: the package manager spago and IDE based on its own language server.

Below you can find the example of a simple button component written in [Halogen](https://purescript-halogen.github.io/purescript-halogen/):

```purescript
module Example.Basic.Button (component) where

import Prelude

import Halogen as H
import Halogen.HTML as HH
import Halogen.HTML.Events as HE
import Halogen.HTML.Properties as HP

type State = { enabled :: Boolean }

data Action = Toggle

component :: forall q i o m. H.Component q i o m
component =
H.mkComponent
    { initialState
    , render
    , eval: H.mkEval $ H.defaultEval
        { handleAction = handleAction }
    }

initialState :: forall i. i -> State
initialState _ = { enabled: false }

render :: forall m. State -> H.ComponentHTML Action () m
render state =
let
    label = if state.enabled then "On" else "Off"
in
    HH.button
    [ HP.title label
    , HE.onClick \_ -> Toggle
    ]
    [ HH.text label ]

handleAction :: forall o m. Action
  -> H.HalogenM State Action () o m Unit
handleAction = case _ of
Toggle ->
    H.modify_ \st -> st { enabled = not st.enabled }
```

For further study, you can proceed to the [official website](https://www.purescript.org/).

### 4. Agda

Haskell works really well when it comes to developing programming languages! Agda is another example.  This is a language with a strong theoretical background and dependent types whose syntax looks much like that of Haskell. Moreover, this is also an automated theorem proving system: logical assertions are expressed as types, and successful type checking is the proof of program correctness.

What's this all for? First of all, this allows avoiding a vast number of run-time errors and to some extent prevents the programmer from writing incorrect code, as utopian as it may sound. Let’s consider a classic example: we’d like to rewrite the `head` function that takes the list head but we want to make sure that we don’t pass an empty list to this function anywhere in our program.

```agda

-- Natural numbers in the form of
-- Peano numbers and their addition
data Nat : Set where
  zero : Nat
  suc  : Nat -> Nat

_+_ : Nat -> Nat -> Nat
 zero  + m = m
 suc n + m = suc (n + m)

-- Vector, dependent type whose length
-- is stored in the type
data Vec (A : Set) : Nat -> Set where
  []   : Vec A zero
  _::_ : {n : Nat} -> A -> Vec A n -> Vec A (suc n)

-- head that cannot be applied to an empty vector
head : {A : Set}{n : Nat} -> Vec A (suc n) -> A
head (x :: xs) = x
```

### 5. PostgREST

PostgREST is an independent web server that will turn your database schema directly into RESTful API. This approach saves you the trouble of writing the boilerplate for CRUD and allows you to focus on the important details of business logic. The advantages include the use of PostgreSQL binary protocol and serialization of JSON directly to SQL to improve performance.

Let’s take a simple city and country scheme as an example:
![PostgREST takes your database schema...](https://typeable.io/images/hasktools/db_schema.png)

As the result, we get the following API for this scheme:
![...and converts it into API](https://typeable.io/images/hasktools/db_api.png)

Documentation is [here](https://postgrest.org/en/v8.0/index.html).

### 6. Octopod

Octopod is a service we developed in Typeable that allows our team to use the entire Helm’s potential without the need for technical knowledge. Our solution makes it easier to manage dynamic environments for the whole team: DevOps, developers, testers, and project managers. All you need is to indicate the URL to the Helm repository and Octopod will automatically get the required configurations.

We wrote about this service [earlier](https://typeable.io/blog/2021-02-18-octopod-release.html), and you can find more information on [Octopod home page](https://typeable.io/octopod.html).

### 7. Pandoc

Pandoc is a multitool that allows converting data in one text format into a totally different format. The utility understands a lot of useful syntax extensions, including the document metadata: author, heading, dates, footnotes, tables, highlighting of code snippets, LaTex inserts with formulas, etc. Supported document formats include Markdown, epub, docs, RTF, ODT, HTML, LaTeX, various formats of wiki markdown and bibliography.

You can download the tool and view all supported formats [here](https://pandoc.org/).

I didn’t list all supported conversion options as it would’ve taken all the post. Just look at the graph showing what and how can be converted:
[a big picture!](https://typeable.io/images/hasktools/pandoc.jpg)

## Conclusion

Here I’ve listed the open-source projects which I believe to be the most interesting and useful for a wide circle of users. This list can be used as an answer to the question “Is there anything useful written in Haskell beyond the science?”

Surely, the list is not exhaustive and can be extended. If you think that it should include a certain project or just want to share a cool Haskell tool – let us know and leave a comment!