Haskell for madmen: Types of TODO
Tags: haskell, tutorial
Published: 2019-10-31 09:56:26

---
title: Haskell for madmen: Types of TODO
series: Haskell for madmen
cover_image: https://thepracticaldev.s3.amazonaws.com/i/u90q8rnyiz6609avk97k.jpg
tags: #Haskell, #tutorial
canonical_url: https://drbearhands.com/haskell-tutorial/4.types-of-todo/
published: true
---

_Post from my [blog](https://drbearhands.com/haskell-tutorial/4.types-of-todo/). If you're enjoying the series, please consider [buying me a coffee](https://ko-fi.com/drbearhands)._

Now that we have a very basic webserver, we must decide what it is we actually want to create to proceed any further. On [request by David Wickes](https://dev.to/gypsydave5/comment/cpo8) I decided to make a "todo-mvp" for the purpose of this tutorial. We won't be following the specifications exactly because ~~I couldn't be arsed to read them~~ there are things I want to discuss beyond what makes sense for a todo-mvp.

# Basic types

First, let's create the data-type that will hold the todo list's information. We need a list of tasks, each task must have a state; "done" or "not done". Let's first create a type to differentiate between "done" and "not done". And no, we won't be using a boolean. Haskell lets us be more specific than that.

```haskell
data TaskStatus = Done | NotDone
```

This creates a type called `TaskStatus`, which is inhabited by `Done` and `NotDone`.
We can use our `TaskStatus` in the definition of a `Task`:

```haskell
data Task = Task String TaskStatus
```

The first `Task` is the type name, the second `Task` is the constructor name. `Done` and `NotDone` are also constructors, they just don't take any arguments. The `Task` constructor, on the other hand, requires a `String` and a `TaskStatus` as an argument. A constructor can be used as a function, so we can create a value of type `Task` like so:

```haskell
myTask :: Task
myTask = Task "create todo list" NotDone
```

When defining a type with only one constructor, it is common for the type's name and the constructor name to be the same. Since types and terms can't occur in the same place, the compiler will have no trouble figuring out which one we mean.

> ##### note
> We can also create types as records:
> ```Haskell
data Task = Task
  { description :: String
  , status :: TaskStatus
  }
```
> this can be useful to name the fields of your type, but I won't go into records yet.

Finally, we want to have a list of tasks:

```haskell
myTodoList :: [Task]
myTodoList =
  [ Task "create todo list" Done
  , Task "invent terror drones" NotDone
  , Task "achieve world domination" NotDone
  ]
```

Just like `IO`, `List` is a higher-kinded type with kind `* -> *`. It takes a type and produces the type for a list of elements of that type. `List Int` is a list of integers, `List String` is a list of strings, `List (List Boolean)` is a list of a list of booleans, and so on.

> ##### note
> List is also a monad. We get `return` by putting a single element in a list, `fmap` by `map` and we can get `>>=` using concatenation `concat :: [[a]] -> [a]` by doing an `fmap` followed by a `concat`. Many other data structures are monads too.

We'll want to send our todo list as HTML, so we must make a function to convert `[Task]` into HTML. Let's start with a conversion function for a single task:

```haskell
toHTML :: Task -> String
toHTML task =
  case task of
    Task description status ->
      case status of
        NotDone -> "<p>" ++ description ++ "</p>"
        Done -> "<p><strike>" ++ description ++ "</strike></p>"
```

What's going on here? We're using a case expression. A case expression is similar to a switch in imperative programming; it evaluates a different expression based on the value of a variable. Rather than matching an exact value though, we match on patters. The pattern `NotDone` matches a `TaskStatus` created with the `NotDone` constructor. Similarly, the pattern `Task description status` matches any value of type `Task` created with the `Task` constructor. In that case `description` and `status` would bind to the first and second argument of the constructor, and we could use them on the right side of the arrow.

`++` is the string concatenation operation.

Oh, and Haskell is indentation-sensitive.


Finally, let's make a function that turns our snippets of HTML into a web page.

```haskell
toHTMLPage :: String -> String
toHTMLPage innerHTML =
  "<!DOCTYPE html>\
  \<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"\" xml:lang=\"\">\
  \<head>\
  \  <meta charset=\"utf-8\" />\
  \  <title>TODO list </title>\
  \</head>\
  \<body>\
  \ " ++ innerHTML ++
  "</body>"
```

We use `\` to escape a newline, and top escaping at the next `\`. This might seem obnoxious at first because it's a lot more characters than using a multi-line string delimiter, but this allows us to have the right indentation in both code and output. We also use `\` to escape the `"` string delimiter.

Run `stack build` to ensure you have no type errors.

# Hoogle

But there's a problem, the `responseLBS` function from last chapter only accepts a lazy `ByteString`, whereas here we have a `String`. So what is the difference? A `String` is a list of `Char`s, whereas a `ByteString` is an array of bytes. A `Char` is a representation of unicode code point, a byte is (generally) 8 bits with no meaning attached to it.

So what is the distinction between a lazy and a strict `ByteString`? Isn't everything in Haskell lazy? Well, this is a different sort of lazy. A strict `ByteString` is a single vector of bytes. But because Haskell is pure, we cannot mutate it. That means that if we need to change or append 1 byte, we have to deep copy everything else in the `ByteString`. A lazy `ByteString` consists of multiple vectors of bytes, so we can copy *references* to the parts that didn't change.

So, how do we change a list of code points into a sequence of bytes? We have to specify the right encoding. We could use the `Data.ByteString.Lazy.Char8` module that comes with the bytestring package, but the documentations tells us "all Chars will be truncated to 8 bits", which is not what we want! HTML supports more than just ASCII characters.

Let's Hoogle it!

Visit [hoogle.haskell.org](https://hoogle.haskell.org) and search for "String -> ByteString". These are the results I get:

![pack :: String -> ByteString in package bytestring, fromString :: String -> ByteString in package utf8-string and others](https://thepracticaldev.s3.amazonaws.com/i/f7mxjy1trycksc5jibzr.png)

We've already rejected the first result, but fromString in the utf8-string package looks promising.

Add the right version of utf8-string under dependencies in `package.yaml`. My dependencies now look like this (you may have different versions):

```yaml
dependencies:
- base >= 4.7 && < 5
- warp >= 3.2.28 && < 4
- wai >= 3.2.2.1 && < 4
- http-types >= 0.12.3 && < 0.13
- utf8-string >= 1.0.1.1 && < 2
```

We'll need to import a new module, namely `Data.ByteString.Lazy.UTF8`:

```haskell
import qualified Data.ByteString.Lazy.UTF8 as UTF8 (fromString)
```

Now, we can change our `requestHandler` to send a task as response:

```haskell
requestHandler :: Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
requestHandler request respond =
  let
    htmlPage = UTF8.fromString $ toHTMLPage $ toHTML myTask
    response = responseLBS status200 [] htmlPage
  in
    do
      putStrLn "Received an HTTP request!"
      respond response
```

Now you can `stack run` to start your server and navigate to `http://localhost:8080` to see a rather disappointing website.

# Typeclasses

Okay, so we can now send a single `Task` as an HTML element, but we want to send more than just that! We need to be able to at least convert a list of tasks to HTML and possibly other stuff too. We want different types to be able to have similar functions available, and be able to write code based on those functions, rather than for each individual type. Enter typeclasses! A typeclass defines a set of functions that must be available for a type for it to be considered a member of that class.

For instance, for our toHTML function, we might make an `HTML` class:

```haskell
class HTML a where
  toHTML :: a -> String
```

Here we create a class `HTML`, we use `a` as a placeholder for the yet unknown type, and declare that a member of the class `HTML` must specify a function called `toHTML` with type signature `a -> String` (where `a` will be replaced by the type in question).

We can declare that `Task` is an instance of the `HTML` class:

```haskell
instance HTML Task where
  toHTML task =
    case task of
      Task description status ->
        case status of
          NotDone -> "<p>" ++ description ++ "</p>"
          Done -> "<p><strike>" ++ description ++ "</strike></p>"
```

By providing an implementation of the requirements for being a member of the `HTML` class, we have essentially proven that `Task` is a member of `HTML`.

We can do something similar for lists:

```haskell
instance HTML a => HTML [a] where
  toHTML listOfElements =
    let
      elementToListElement :: HTML a => a -> String
      elementToListElement element = "<li>" ++ toHTML element ++ "</li>"
    in
      "<ul>" ++ (concat $ map elementToListElement listOfElements) ++ "</ul>"
```

There is a lot of new stuff in there, so let's look at it bit by bit.

What is this weird `=>` arrow? Well it's a sort of restriction to the type signature that comes after it. `instance HTML a => HTML [a]` is saying that `[a]` is an instance of the `HTML` class, but only if the variable type `a` is as well. So a `[Task]` is an instance of `HTML`, because `Task` is, but `[Char]` is not, because `Char` is not an instance of `HTML` (not yet anyway). This restriction on the type variable `a` tells us `a` must follow the rules of the `HTML` class. Specifically, there must be a function `toHTML :: a -> String`, and we will be able to use that function when declaring `toHTML` for `[a]`.


Similarly, in `elementToListElement`, `HTML a` tells us this function only works for instances of the `HTML` class, letting us use the `toHTML` function.

Finally, we find the functions `map` - which you're likely familiar with, it creates a new list by applying a function to all elements of another list - and concat, which concatenates a list of `String`s into a single `String`.


### The open world assumption

Now, you might want to also make a `String` an instance of `HTML`. Unfortunately, you cannot do that, because `String` is defined as being a list of characters `[Char]`. We already have an instance for `[a]`, and `[Char]` is also a `[a]`. If we were to declare:

```haskell
instance Html [Char] where -- Bad!
  toHTML = ...
```

the compiler would complain, because it is no longer clear which implementation of `toHTML` to use. Even if we were to remove the instance declaration for `[a]`, it would still be illegal, as we might add it later, potentially changing the behavior of code in a completely different place. We say it violates the *open world assumption*. We do not know what else there is, so we are only allowed to match instances on data declarations.

But how can a `String` not be a data declaration? We can create aliases for existing types:

```haskell
type String = [Char]
```

This defines the `String` type to be a different name for the `[Char]` type. If we had:

```haskell
data String = String [Char]
```

We would not have this problem. It is not a popular opinion, so take it with a grain of salt, but I personally consider `type` declarations to be bad style: things that are the same should be called by the same name, otherwise we're just obfuscating the types. Aliases can save you some time though, and I have used them myself, but I'm never proud of them.

> ##### side note 1
> Instance declarations match on the right side of the `=>`. That means that even if you were to used advanced type programming to make the left sides of two instance declarations mutually exclusive, you still would not be able to have overlapping instances.

> ##### side note 2
> There is a language extension that will let you have overlapping instances, but I do not recommend it.


# Putting it all together

We can now also change our `toHTMLPage` to be defined in terms of the `HTML` class:

```haskell
toHTMLPage :: HTML a => a -> String
toHTMLPage a =
  "<!DOCTYPE html>\
  \<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"\" xml:lang=\"\">\
  \<head>\
  \  <meta charset=\"utf-8\" />\
  \  <title>TODO list </title>\
  \</head>\
  \<body>\
  \ " ++ toHTML a ++
  "</body>"
```

And of course don't forget to change `requestHandler` to work with our new definition! And let's send the entire list over while we're at it.

```haskell
htmlPage = UTF8.fromString $ toHTMLPage myTodoList
```

`stack run` it and let's see our website:

![todo list website](https://thepracticaldev.s3.amazonaws.com/i/c5t91g1e1uxx5v6ve2lv.png)

Great success!

[Final code for this chapter](https://gitlab.com/DrBearhands/haskell-tutorial/tree/4-types-of-todo).