Creating a Haskell Application Using Reflex. Part 1
Tags: haskell, functional, programming, tutorial
Published: 2021-03-15 14:26:12

Author: Nikita Anisimov

[Part 2](https://dev.to/typeable/creating-a-haskell-application-using-reflex-part-2-4jaa)

[Part 3](https://dev.to/typeable/creating-a-haskell-application-using-reflex-part-3-47d6)

[Part 4](https://dev.to/typeable/creating-a-haskell-application-using-reflex-part-4-4jn7)

# Introduction

Hi there! My name is Nikita. At Typeable, we develop frontend for some of our projects using the FRP approach, specifically, its Haskell implementation – [`reflex`](https://reflex-frp.org/) web-framework. The resources that offer guidelines for this framework are quite limited, so we decided to fill this gap more or less.

In this series of posts, we will describe how a Haskell web application can be developed using [`reflex-platform`](https://github.com/reflex-frp/reflex-platform). `reflex-platform` offers `reflex` and `reflex-dom` packages. `reflex` package is the Haskell implementation of [Functional reactive programming (FRP)](https://en.wikipedia.org/wiki/Functional_reactive_programming). `reflex-dom` library contains a large number of functions, classes, and types used when dealing with `DOM`. The packages are separated as it is possible to use the FRP approach not only for web-development. We will develop the`Todo List` application that allows carrying out various manipulations on the task list.

![](https://blog.typeable.io/images/reflex/1.gif)

>Understanding this series of articles requires some knowledge of Haskell programming language, so it will be useful to get an idea of the functional reactive programming first.

I won’t provide a detailed description of the FRP approach. The only thing worth mentioning is the two basic polymorphic types the approach is based on:

* `Behavior a` is a reactive time-dependent variable. It is a certain container that holds a value during its entire life cycle.
* `Event a` is an event that occurs in the system. It carries information that can only be retrieved when the event fires.
`reflex` package also offers another new type:
* `Dynamic a` is the combination of `Behavior a` and `Event a`, i.e. this is a container that always holds a certain value and, similarly to an event and unlike `Behavior a`, it can notify about its change.

`reflex` deals with the notion of a frame, i.e. a minimum time unit. A frame starts together with the occurred event and lasts until the data processing in this event stops. An event can produce other events generated, for instance, by filtering, mapping, etc. In this case, these dependent events will also belong to the same frame.

# Preparation
First of all, we will need to install `nix` package manager. The installation procedure is described [here](https://nixos.org/download.html).

It makes sense to configure `nix` cash to speed up the build. If you don’t use NixOS, add the following lines to `/etc/nix/nix.conf`:
```nix
binary-caches = https://cache.nixos.org https://nixcache.reflex-frp.org
binary-cache-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=
binary-caches-parallel-connections = 40
```
If you use NixOS, add the following to `/etc/nixos/configuration.nix`:
```nix
nix.binaryCaches = [ "https://nixcache.reflex-frp.org" ];
nix.binaryCachePublicKeys = [ "ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=" ];
```

In this tutorial, we will use the standard structure consisting of three packages:

* `todo-client` is the client part;
* `todo-server` is the server part;
* `todo-common` contains shared modules used by the server and the client (for instance, API types).

After that, it is necessary to prepare the development environment. Follow the steps described in the [documentation](https://github.com/reflex-frp/reflex-platform/blob/develop/docs/project-development.rst):

* Create the application directory: `todo-app`;
* Create projects `todo-common` (library), `todo-server` (executable), `todo-client` (executable) in `todo-app`;
* Configure build using `nix` (file `default.nix` in directory `todo-app`);
  * Also don’t forget to enable option `useWarp = true;`;
* Configure `cabal` build (files `cabal.project` and `cabal-ghcjs.project`).

At the moment of publication of this post, `default.nix` will look something like this:
```nix
{ reflex-platform ? ((import <nixpkgs> {}).fetchFromGitHub {
    owner = "reflex-frp";
    repo = "reflex-platform";
    rev = "efc6d923c633207d18bd4d8cae3e20110a377864";
    sha256 = "121rmnkx8nwiy96ipfyyv6vrgysv0zpr2br46y70zf4d0y1h1lz5";
    })
}:
(import reflex-platform {}).project ({ pkgs, ... }:{
  useWarp = true;
  packages = {
    todo-common = ./todo-common;
    todo-server = ./todo-server;
    todo-client = ./todo-client;
  };
  shells = {
    ghc = ["todo-common" "todo-server" "todo-client"];
    ghcjs = ["todo-common" "todo-client"];
  };
})
```
> Note: the documentation suggests cloning `reflex-platform` repository manually. In this example, we used `nix` tools to get it from the repository.

During client development, it is convenient to use the `ghcid` tool which automatically updates and relaunches the application after the source code changes.

To make sure that everything is working as intended, add the following code to `todo-client/src/Main.hs`:

```Haskell
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Reflex.Dom
main :: IO ()
main = mainWidget $ el "h1" $ text "Hello, reflex!"
```

The development is carried out in `nix-shell`, which is why you have to open this shell at the very beginning:
```sh
$ nix-shell . -A shells.ghc
```

To start through `ghcid`, type in the following command:
```sh
$ ghcid --command 'cabal new-repl todo-client' --test 'Main.main'
```

If everything is working, you’ll see `Hello, reflex!` at`localhost:3003`.

![](https://blog.typeable.io/images/reflex/2.png)

### Why 3003?
The port number is searched for in the  `JSADDLE_WARP_PORT` environment variable. If this variable is not set, value 3003 is used by default.

## How it works
You might have noticed that we used plain `GHC` instead of `GHCJS` during the build. This is possible because we use `jsaddle` and `jsaddle-warp` packages. `jsaddle` package offers a JS interface for `GHC` and `GHCJS`. Using the `jsaddle-warp` package we can start the server that will update `DOM` using web-sockets and act as a JS-engine. Just to this end, we set the flag `useWarp = true;`, otherwise, the `jsaddle-webkit2gtk` package would have been used by default and we would see the desktop application during the start. It’s worth mentioning that there are also such interfaces as `jsaddle-wkwebview` (for iOS applications) and `jsaddle-clib` (for Android applications).

# Simplest TODO application
Let’s get down to development!

Add the following code to `todo-client/src/Main.hs`.

```Haskell
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Reflex.Dom
main :: IO ()
main = mainWidgetWithHead headWidget rootWidget
headWidget :: MonadWidget t m => m ()
headWidget = blank
rootWidget :: MonadWidget t m => m ()
rootWidget = blank
```

We can say that the function `mainWidgetWithHead` is the `<html>` element of the page. It accepts two parameters – `head` and `body`. There are also functions `mainWidget` and `mainWidgetWithCss`. The first function accepts only a widget with `body` element. The second one accepts styles, which are added to `style` element, as the first argument, and `body` element as the second argument.

> Any HTML element or an element group will be designated as a widget. A widget can have its event network and produce some HTML code. As a matter of fact, any function generating a result of the type belonging to type classes responsible for `DOM` building can be called a widget.

Function `blank` is equal to `pure ()`, it performs nothing, doesn’t change the `DOM` in any way and does not influence the event network.

Now let’s describe the `<head>` element of our page.

```Haskell
headWidget :: MonadWidget t m => m ()
headWidget = do
  elAttr "meta" ("charset" =: "utf-8") blank
  elAttr "meta"
    (  "name" =: "viewport"
    <> "content" =: "width=device-width, initial-scale=1, shrink-to-fit=no" )
    blank
  elAttr "link"
    (  "rel" =: "stylesheet"
    <> "href" =: "https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
    <> "integrity" =: "sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
    <> "crossorigin" =: "anonymous")
    blank
  el "title" $ text "TODO App"
```

This function generates the following content of `head` element:
```HTML
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
<link crossorigin="anonymous" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
  integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" rel="stylesheet">
<title>TODO App</title>
```

`MonadWidget` class allows building or rebuilding the `DOM` and defining the network of events that occur on the page.

`elAttr` function looks as follows:
```Haskell
elAttr :: forall t m a. DomBuilder t m => Text -> Map Text Text -> m a -> m a
```
It takes the tag name, attributes, and content of the elements. This function, as well as the whole set of `DOM` building functions, returns what is returned by its internal widget. In this case, our elements are empty, which is why we use `blank`. This is one of the most frequent uses of this function, when it is necessary to create an empty element body. `el` function is used in the same way. Its input parameters include only the tag name and content. In other words, this is a simplified version of `elAttr` function without attributes. Another function we use here is `text`. Its task is to display text on the page. This function displays all possible control characters, words, and tags, which is why exactly the text passed to this function will be displayed. Function `elDynHtml` is used to embed an HTML chunk.

It has to be said that in the example above the use of `MonadWidget` is redundant because this part builds an immutable `DOM` area. As stated before, `MonadWidget` allows building or rebuilding `DOM`, as well as defining the network of events. The functions we are using in this case require only the availability of `DomBuilder` class, and here, indeed, we could write only this constraint. However, in general, there are far more constraints on the monad, which may hamper and slow down the development if we write only the classes we need at the moment. This is where we need `MonadWidget` class that looks like some sort of a multitool. For those who are curious, we give the list of all classes working as the `MonadWidget` superclasses:
```Haskell
type MonadWidgetConstraints t m =
  ( DomBuilder t m
  , DomBuilderSpace m ~ GhcjsDomSpace
  , MonadFix m
  , MonadHold t m
  , MonadSample t (Performable m)
  , MonadReflexCreateTrigger t m
  , PostBuild t m
  , PerformEvent t m
  , MonadIO m
  , MonadIO (Performable m)
#ifndef ghcjs_HOST_OS
  , DOM.MonadJSM m
  , DOM.MonadJSM (Performable m)
#endif
  , TriggerEvent t m
  , HasJSContext m
  , HasJSContext (Performable m)
  , HasDocument m
  , MonadRef m
  , Ref m ~ Ref IO
  , MonadRef (Performable m)
  , Ref (Performable m) ~ Ref IO
  )
class MonadWidgetConstraints t m => MonadWidget t m
```
Now let’s move to the page element `body`, after defining the data type we will use for our task:

```Haskell
newtype Todo = Todo
  { todoText :: Text }
newTodo :: Text -> Todo
newTodo todoText = Todo {..}
```

The body will have the following structure:

```Haskell
rootWidget :: MonadWidget t m => m ()
rootWidget =
  divClass "container" $ do
    elClass "h2" "text-center mt-3" $ text "Todos"
    newTodoEv <- newTodoForm
    todosDyn <- foldDyn (:) [] newTodoEv
    delimiter
    todoListWidget todosDyn
```

The input of the `elClass` function includes the tag name, class(es) and content. `divClass` is the shorter version of `elClass "div"`.

All functions mentioned are responsible for visual presentation and bear no logic, as opposed to `foldDyn` function. It is defined in  `reflex` package and has the following signature:
```Haskell
foldDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> b) -> b -> Event t a -> m (Dynamic t b)
```
It looks like `foldr :: (a -> b -> b) -> b -> [a] -> b` and actually plays the same role but uses an event instead of a  list. The resulting value is wrapped in `Dynamic` container because it will be updated with each event. The updating procedure is set by the parameter function with the input consisting of the value from the occurred event and the current value from `Dynamic`. These values are used to form a new value to be stored in `Dynamic`. The update will take place each time the event occurs.

In our example, `foldDyn` will update the dynamic task list (which is initially empty) as soon as a new task is added from the input form. New tasks will be added to the beginning of the list because we use the function `(:)`.

Function `newTodoForm` builds the part of `DOM` containing the task description input form and returns the event bringing the new `Todo`. The occurrence of this event will start the task list update.

```Haskell
newTodoForm :: MonadWidget t m => m (Event t Todo)
newTodoForm = rowWrapper $
  el "form" $
    divClass "input-group" $ do
      iEl <- inputElement $ def
        & initialAttributes .~
          (  "type" =: "text"
          <> "class" =: "form-control"
          <> "placeholder" =: "Todo" )
      let
        newTodoDyn = newTodo <$> value iEl
        btnAttr = "class" =: "btn btn-outline-secondary"
          <> "type" =: "button"
      (btnEl, _) <- divClass "input-group-append" $
        elAttr' "button" btnAttr $ text "Add new entry"
      pure $ tagPromptlyDyn newTodoDyn $ domEvent Click btnEl
```

The first innovation we see here is the `inputElement` function. Its name speaks for itself, as it adds an `input` element. It takes on `InputElementConfig` type as the parameter. It has a lot of fields, inherits several different classes, but adding the required attributes to this tag is the most interesting in this case. This can be done using `initialAttributes` lens. Function `value` is a method of `HasValue` class returning the value existing in this `input`. For the `InputElement` type, it has the type of `Dynamic t Text`. This value will be updated after each change in the `input` field.

The next change we can notice here is the use of `elAttr'` function. The difference between the functions with a stroke and the functions without one for `DOM` building is that these functions additionally return the very page element we can manipulate. In our case, we need it to obtain the event of clicking on this element. `domEvent` function serves this purpose. This function assumes the name of the event – in our case, `Click` – and the element the event is related to. The function has the following signature:

```Haskell
domEvent :: EventName eventName -> target -> Event t (DomEventType target eventName)
```
Its return type depends on the event type and the element type. In our case, this is `()`.

The next function we see is `tagPromptlyDyn`. Its type is as follows:
```Haskell
tagPromptlyDyn :: Reflex t => Dynamic t a -> Event t b -> Event t a
```
If the event is triggered, the task of this function will be to place the value presently existing inside `Dynamic` into the event. That is, the event resulting from function `tagPromptlyDyn valDyn btnEv` occurs simultaneously with `btnEv` but carries the value held by `valDyn`. In our example, this event will occur after a button click and carry the value from the text field.

Now it has to be mentioned that functions containing the word `promptly` in their name are potentially dangerous as they can call cycles in the event networks. On the surface, this will look as if the application got hung up. Where possible, `tagPromplyDyn valDyn btnEv` call should be replaced with `tag (current valDyn) btnEv`. Function `current` receives `Behavior` from `Dynamic`. These calls are not always interchangeable. If a `Dynamic` update and an `Event` event in `tagPromplyDyn` occur at the same moment, i.e. in one frame, the output event will contain the data which `Dynamic` obtained in this frame. If we use `tag (current valDyn) btnEv`, the output event will contain the data the initial `current valDyn`, i.e. `Behavior`, had in the previous frame.

Now we’ve come down to another difference between `Behavior` and `Dynamic`: if `Behavior` and `Dynamic` are updated within one frame, `Dynamic` will be updated in this frame, while `Behavior` will have a new value in the next one. In other words, if the event took place at some point in time `t1` and some point in time `t2`, `Dynamic` will have the value brought by event `t1` within time period `[t1, t2)`, and `Behavior` will have the value brought during `(t1, t2]`.

Function `todoListWidget` displays the entire `Todo` list.

```Haskell
todoListWidget :: MonadWidget t m => Dynamic t [Todo] -> m ()
todoListWidget todosDyn = rowWrapper $
  void $ simpleList todosDyn todoWidget
```
Here we meet the function `simpleList`. It has the following signature:
```Haskell
simpleList
  :: (Adjustable t m, MonadHold t m, PostBuild t m, MonadFix m)
  => Dynamic t [v]
  -> (Dynamic t v -> m a)
  -> m (Dynamic t [a])
```
This function is a part of `reflex` package. In our case, it is used to arrange duplicate elements in `DOM`, where `div` elements will be listed one after another. It takes on the changing in time  `Dynamic` list and the function used to process each element separately. Here this is just a widget used to display one element of the list:
```Haskell
todoWidget :: MonadWidget t m => Dynamic t Todo -> m ()
todoWidget todoDyn =
  divClass "d-flex border-bottom" $
    divClass "p-2 flex-grow-1 my-auto" $
      dynText $ todoText <$> todoDyn
```

Function `dynText` differs from function `text` in that its input contains the text wrapped in `Dynamic`. If a list element is changed, this value will also be updated in `DOM`.

We also used two more functions not mentioned before – `rowWrapper` and `delimiter`. The first function is the widget wrapping. It has nothing new and looks as follows:
```Haskell
rowWrapper :: MonadWidget t m => m a -> m a
rowWrapper ma =
  divClass "row justify-content-md-center" $
    divClass "col-6" ma
```
Function `delimiter` just adds a delimiting element.
```Haskell
delimiter :: MonadWidget t m => m ()
delimiter = rowWrapper $
  divClass "border-top mt-3" blank
```

![](https://blog.typeable.io/images/reflex/3.png)

The result we obtained can be viewed in [in our repository](https://github.com/typeable/blog-posts-ru/tree/680581203f0fd5f7fe0714d9d8778e9426010ea7).

This is all you need to build a simple incomplete `Todo` application. In this part, we described the environment configuration and began developing the application. In the next part, we’ll add operations on the list elements.