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. 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 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):
A config example (only a part is shown, not the entire config):
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 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.
Let’s use the following script by way of example (try to find the errors in it without looking into the ShellCheck result):
#!/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:
3. PureScript
Haskell was used to develop several popular compiled functional languages for the frontend development which are eventually transpiled into JavaScript. 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:
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.
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.
-- 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:
As the result, we get the following API for this scheme:
Documentation is here.
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, and you can find more information on Octopod home page.
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.
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!
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!
Top comments (4)
A fun and informative read as always. Great job!
Thank you!
Thank you for sharing this list of tools based on purely functional programing language.
We're glad you find our content interesting!