# Learning Elm Data Types

In this post I take a short meander through the Elm Dict module.

#### Dictionaries

Elm has a Dict type which stores key, value pairs. To store the simplest example I can think of we can use:

> a = Dict.insert 'a' 1 Dict.empty

Dict.fromList [('a',1)] : Dict.Dict Char number

The first line, is relatively simple to understand: it inserts a key, value pair into an empty Dict. It’s pretty verbose, and as a learner I find the ‘.fromList’ somewhat confusing. No doubt as I get more into the language this syntax style will start to feel more comfortable.

Next up, to update this Dict we can use the following:

> b = Dict.update 'a' (\_ -> Just 2) a

Dict.fromList [('a',2)] : Dict.Dict Char number

In the example above, we’re just updating the value of the original Dict, *a*, from 1 to 2. Elm expects the second argument of *update *to be a function which has a type signature of *Maybe a-> Maybe a*, where *a* is the type of the value in the key, value pair (we’re using integers).

The example above uses a function which always updates our Dict value to 2 — the underscore in the anonymous function means that the input parameter is ignored.

To do something more useful, we need to roll out a whole new named function. The function below accepts a *Maybe Int*. If the input is good it returns the same Maybe type with its contents multiplied by 3, otherwise if the value doesn’t exist it returns Just 0.

times3 : Maybe Int -> Maybe Int

times3 x =

case x of

Just num -> Just <| num * 3

Nothing -> Just 0

Update:times3

As an aside, an alternative implementation of functionabove, using function composition is:

times3' = Maybe.withDefault 0 >> (*) 3 >> Just

Which we can test using:

> c = Dict.update 'a' times3 b

Dict.fromList [('a',6)] : Dict.Dict Char number

So far so good!

#### Lets iterate on this!

The Dict module also has some functions that iterate over all the key, value pairs in the supplied dictionary. Here’s we’ll take a quick look at a couple of cases.

Firstly, let’s start with some test data:

> a = Dict.fromList [('a', 1), ('b', 2), ('c', 3)]

Dict.fromList [('a',1),('b',2),('c',3)] : Dict.Dict Char number

According to the Elm docs, the Dict module exposes a *map* function with the following type signature:

**map** : (comparable -> a -> b) -> Dict comparable a -> Dict comparable b

For a time I scratched my head, wondering what a *comparable* was. It turns out it’s the dictionary key. In the examples we’ve been using so far the key has been a simple *Char*. The second and third arguments are both Dict’s containing key, value pairs — the values are expressed as *a* and *b*. This means would could map over a Dict containing values of one type and return another Dict containing values of a different type, say from *Int* to *String*, say. However, in our simple case both *a* and *b* are the same type, namely *Int*. Therefore, the *map* function’s first argument needs to be a function that takes a *Char* and *Int*, and returns an *Int*.

b = Dict.map (\key value -> value * 4) a

Dict.fromList [('a',4),('b',8),('c',12)] : Dict.Dict Char number

In the example above, we using an anonymous function that takes a key, value pair, and returns the value multiplied by 4. Note, we’re not using the key parameter, and to be honest I’m not sure why you’d want the key in a map expression. But, the mysteries of a new language reveal themselves gradually, so let’s move on.

#### To fold left or right? That is the question!

Just to get more familiar with Elm method type signatures, let’s look another example: *foldl*.

**foldl** : (comparable -> v -> b -> b) -> b -> Dict comparable v -> b

Firstly, we see some *comparable*’s again, which we’re now familiar with. *v* is our value from our key, value pairs, but what’s *b*?

Currently, the Elm docs don’t give any description of *b*, nor an example use case. (I miss the Elixir docs already). So I dredged from the depths of my memory what *foldl *(sometimes known as reduce) does in other languages.

Normally, *foldl* takes a function, an initial value, plus a collection of some sort. So if we wanted to implement *sum* using *foldl*, the arguments would be an addition function, 0 and a list of integers, say. Thus, I deduced that b is of type *Int*, in our case. Therefore, we need to write a function, for the first argument, that takes *Char*, *Int*, *Int*, and returns *Int*.

> c = Dict.foldl (\key x acc -> acc + x) 0 b

24 : number

So, this example iterates over the contents of our Dict, *b*, accumulating the values as it goes. As before, we’re not using the key; I look forward to seeing an example where this is used.

Well, that wraps it up for this time. I hope some of it made sense!

p.s. The online editor, try-elm is really useful for trying out larger chunks of Elm code. Here’s a snippet I prepared earlier.