---
title: Gotta Catch an Elm
teaser: Using the PokeApi to learn a new language.
tags: elm,functional programming,learning
author: EJ Mitchell
published_on: 2020-07-13
---

When I first started at thoughtbot, my primary experience was in Rails and
TypeScript. However, the first project I joined was written in Elm and Scala.
Both are pretty different from my "native" languages: they are **strictly**
**typed** and utilize **functional programming** patterns. But, getting
onboarded with Elm was much easier than with Scala. There were many reasons for
this, one of them being that Elm has a famously descriptive and easy-to-use
compiler that gave me very direct messages about what I needed to fix. Despite
this, though, I often found myself wondering why things had to be done in such
specific ways. What was a `Cmd`? What was a `Msg`? Why did I even need them? I
resolved that the best way to find out was to build something every 90’s kid
dreamed of having.

If you guessed a Pokedex, then you either really wanted one too or you just read
the title to my post. Either way, good job!

It turns out that what goes into a Pokedex is perfect for a beginner app. All
you need to be able to do is search for the name of a Pokemon and display the
information you want about that Pokemon. Conveniently - as if I planned it or
something - there is also a well laid out and detailed API called the
[PokeApi](https://pokeapi.co/).

With that in mind, my next step (apart from reading [the Elm
docs](https://guide.elm-lang.org/), of course), was to figure out what I wanted
on the page. In addition to a search bar, I decided that I was going to also
make a “Get Random Pokemon” button, which would introduce me to how Elm handles
random numbers - since, spoiler alert, random numbers are handled differently in
functional programming languages.

So, written out, here are the steps I followed to make the app:

1. Set up the configuration to get a simple “hello world” page.
2. Build a “Get Pokemon” button that only returned the PokeAPI response from one
   URL.
3. Expand from a “Get Pokemon” to “Get Random Pokemon” button.
4. Build a simple decoder that takes the API response and returns just a name.
5. Add onto that decoder to get more deeply nested values from the response and
   build a Pokemon record.
6. Move on to making a search bar, using Elm’s `onInput` functionality.

It seems like this would be slow, but it worked well to better understand some
idiosyncrasies in Elm. Of course, there were some gotchas to this process that
were unique to Elm that made things slower. However, there were also some
victories to using this elegant, strictly-typed language that really made me
feel like I was catching ‘em all.

## Starting the app and getting a “Hello World” page

After installing Elm, all you need to do is go to your project folder and type
`elm init`. That’s it. o(≧▽≦)o

Typing `elm init` gets a basic folder structure started - it will prompt you to
make an `elm.json` file which keeps track of the packages you use (like
`package.json` does for `npm` projects). It will also make an `src` folder where
it will look for files you’ve created in your Elm project.

From here all I needed to do was set up a server and a `Main.src` file.
Depending on how you set up your project, the compiler might also give you
further steps to follow. As I’ve mentioned at the beginning of this post, Elm is
thankfully _really_ good in this department. You will almost never be left
scratching your head at a response from the compiler. Here's an example of the
`elm init` output in the terminal:

```
❯ elm init
Hello! Elm projects always start with an elm.json file. I can create them!

Now you may be wondering, what will be in this file? How do I add Elm files to
my project? How do I see it in the browser? How will my code grow? Do I need
more directories? What about tests? Etc.

Check out <https://elm-lang.org/0.19.0/init> for all the answers!

Knowing all that, would you like me to create an elm.json file now? [Y/n]:
```

Personally, I used `nginx` for the server, since I’ve used it for previous
projects and knew how to set it up quickly. There are other options here like
[Create Elm App](https://github.com/halfzebra/create-elm-app), [Elm
Live](https://www.elm-live.com/), and [Parcel](https://parceljs.org/elm.html).
However, if you are doing something super simple, you can also just run [`elm
reactor`](https://elmprogramming.com/elm-reactor.html) with no extra packages
needed.

To get a `Main.elm` file started, I followed the example on [this
page](https://guide.elm-lang.org/effects/json.html), since I knew my end goal
was to serve the result of a decoded JSON response and nothing super fancy. I
cut out everything but one `Model` variant to have a result like this:

```elm
import Browser
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)

-- MAIN

main =
  Browser.element
    { init = init
    , update = update
    , subscriptions = subscriptions
    , view = view
    }

-- MODEL

type Model
  = HelloWorld

init : () -> (Model, Cmd Msg)
init _ =
  (HelloWorld, Cmd.none)


-- UPDATE

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  (HelloWorld, Cmd.none)

-- SUBSCRIPTIONS

subscriptions : Model -> Sub Msg
subscriptions model =
  Sub.none


-- VIEW

view : Model -> Html Msg
view model =
  div []
    [ h2 [] [ text "Hello world!" ]]
```

From there, all I had to do was run `elm make Main.src` and start up my server.

**TL;DR**: Elm makes starting up very straightforward, and there are many ways
to serve and tweak your configuration to make it even easier for you and your
team.

## Fetching raw data from an API

Elm also makes this process pretty straightforward. I needed to make sure my
`view` had a button with an `onClick` event handler. If you come from something
like React or Angular, `onClick` acts very much the same to what you know,
though instead of calling a function right there, Elm sends a “message” to its
`update` function. In other words, instead of making a new function called
`getMeAPokemon()` that handles all of the logic, I needed to create some new
“messages” and “commands” in the `update` function of my app.

What does this mean? This is a part of the [Elm
architecture](https://guide.elm-lang.org/architecture/). Of all things, this was
the hardest to wrap my head around at first. What makes Elm different from the
pack, and what might take some extra mental chewing, is that you send “messages”
around in your app when things change states, and paired with those messages are
“commands”. These commands are sometimes _side-effects_ that do _something_
outside of your app. In this app, as you will see below, it is to complete an
HTTP request. Sometimes these commands are just... well... nothing. This is
reflected as `Cmd.none`, which means that the process being completed has no
side-effect.

Here, the `onClick` triggers a `Msg`, which is sent to the `update` function.
The `Msg` waves its arms saying “Hey, this button was clicked!" The `update`
function then knows what to do with this information based on the `case`
statement. The `case` statement then directs you to the `Cmd` that makes a GET
request to the PokeAPI and returns its response. When I get that response (a
`Result`), another `Msg` waves its arms saying “Now I’ve got something from the
API”. This `Msg` (`RandomPokemonResponse`) is then sent back to the `update`
function and, like before, it has a branch in the `case` statement with the
appropriate course of action.

What makes `RandomPokemonResponse` only slightly different than the first `Msg`
we saw is that the `Result` tags along with it. This is so the `Result` can be
dealt with as well: showing the user the info about the Pokemon if the `Result`
is "good" or showing an error when the `Result` is "bad". That’s it. Hopefully
this peels back some of the noise around the architecture, which definitely
confused me the first time I used it. (Even while I was trying to write this
blog post!) Here is the code below:

```elm
type Msg
= RandomButtonClicked
| RandomPokemonResponse (Result Http.Error String)

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
  case msg of
    RandomButtonClicked ->
      -- Loading is a Model, like HelloWorld except it has the page say "Loading..."
      ( Loading
      , Http.get
        { url = "https://pokeapi.co/api/v2/pokemon/ditto/"
        , expect = Http.expectString RandomPokemonResponse
        }
      )
    RandomPokemonResponse result ->
      case result of
        Ok fullText ->
          ( Success fullText, Cmd.none )
```

The `view` function has a bit of HTML (written out in Elm, which is a point we
will get to later) that looks like this:

```elm
div []
  [ text "Search for a Pokémon:"
  , button [ onClick RandomButtonClicked ][ text "Random Pokemon"]
  ]
```

**TL;DR**: Unless you've written a Redux reducer, this is likely not an
architecture you’ve seen before. This pattern may be what you spend the longest
getting used to.

## Getting a Random Pokemon

From here, I changed the button to get a random Pokemon instead of just Ditto
all the time. This required some finagling, since Elm is a functional
programming language. It requires functions to be
[pure](https://elmprogramming.com/pure-functions.html).

Getting a random number is inherently _impure_: it gets a different number every
time you call it. Pure functions don’t act like that - if you give a pure
function an input `x` and it returns `y`, it will _always_ return `y` with input
`x`. To get around this, I needed to lean heavily on the aforementioned Elm
architecture to do what I wanted.  You can see the extent of my changes to make
this happen in the git diff of `Main.elm`:

```diff
 type Msg
     = RandomButtonClicked
+    | ReceiveRandomId Int
     | RandomPokemonResponse (Result Http.Error String)

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
         RandomButtonClicked ->
             ( Loading
-            , Http.get
-                { url = "https://pokeapi.co/api/v2/pokemon/ditto/"
-                , expect = Http.expectString RandomPokemonResponse
-                }
+            , Random.generate ReceiveRandomId generateRandomNumber
             )

+        ReceiveRandomId id ->
+            buildRandomPokemonResponse id
+
          RandomPokemonResponse result ->
            case result of
                Ok fullText ->
                    ( Success fullText, Cmd.none )
                Err _ ->
                    ( Failure, Cmd.none )


+buildRandomPokemonResponse : Int -> ( Model, Cmd Msg )
+buildRandomPokemonResponse randNumber =
+    ( Loading
+    , Http.get
+        { url = "https://pokeapi.co/api/v2/pokemon/" ++ String.fromInt randNumber
+        , expect = Http.expectString RandomPokemonResponse
+        }
+    )
+
+
+generateRandomNumber : Random.Generator Int
+generateRandomNumber =
+    Random.int 1 150

```

Overall, when working with Elm, apart from the new architecture, you will find
that you don’t always need to know bucketloads about functional programming. In
a lot of ways this is _great_! You can just get up and running with it.
Occasionally, though, there are inklings that leak through ... like [random
numbers](https://medium.com/@ckoster22/randomness-in-elm-8e977457bf1b) or [HTTP
requests](https://jamesbvaughan.com/elm-http-requests/), which are two examples
you'll see in my demo app.

When you start doing more intense things in your apps like mapping or dealing
with “contexts” ([e.g., `Maybe`](https://thoughtbot.com/blog/maybe-mechanics)),
you’re gradually eased in to some of the more hairy topics that languages like
Scala just throw you into. This is one of the many reasons why quite a few
people at thoughtbot recommend learning Elm if you want to get your feet wet
with functional programming or strictly typed languages:

**Not only do you have your hand held by the compiler, but the names of more**
**complex concepts are relatively friendly compared to other languages.**

**TL;DR**: Elm is a functional programming language that doesn’t entirely feel
like one. If you’re new to functional programming, start with Elm!

## Building a Decoder Incrementally

This is notoriously something that gives people a lot of trouble in strictly
typed languages. In Elm, this is no exception. I burned a lot of time working on
decoders in my app. I was lucky that both
[Josh](https://thoughtbot.com/blog/decoding-json-structures-with-elm) and
[Joël](https://thoughtbot.com/blog/5-common-json-decoders) have written about
this, which gave me a good foundation to work off of. Eventually, what I learned
is to build a Decoder **incrementally**. Start small, then begin adding more
detail as you go. In my case, I just started with the name of the Pokemon. Then,
I went about adding things from more nested and complex structures within the
JSON body, like moves and abilities.

I found that by starting small and thinking of each piece as a tiny building
block, I was less likely to make a mistake. It also made me really think about
what I wanted my `Pokemon` type to look like. What information was actually
important to impart to the user? I found that going through the time to make a
decoder for something large (with possibly unnecessary fields) in Elm would take
a great deal longer,  so the likelihood of me putting extra time into something
a user might not want was significantly less. I ended up building a much more
elegant and sparce data structure than I would have in something like TypeScript
or Ruby.

```elm
type alias Pokemon =
  { name: String
  , abilities : List Data
  , moves : List Data
  }

type alias Data =
  { name : String
  , url : String
  }
```

Then, I was able to make a decoder for each attribute in the Pokemon data
structure and use that to make a larger decoder for the Pokemon itself. Here, I
got to use a `map3` function, which is another neat trick from functional
programming that Elm makes accessible to new programmers.

```elm
pokeDecoder : D.Decoder Pokemon
pokeDecoder =
  D.map3 Pokemon nameDecoder abilitiesDecoder movesDecoder
```

**TL;DR**: No matter the language, decoders are no fun when you first start out.
With Elm, though, you are encouraged by the nature of the language to consider
more simplistic data structures. This arguably makes programmers happier when
working with the code. Overall, the ability to compose and reuse decoders
becomes a boon the more complex your app gets. In addition, with Elm's decoders,
the shape of your data is guaranteed after it's been decoded! No more "shotgun
decoding" required (looking at you, JavaScript).

## Building a Search Bar

To try something new, instead of making a “Submit” button, I used Elm’s
`onInput` functionality, which sends out its associated `Msg` when a user types
something into the input.  In this case, when a user types something into the
search bar, I have a `Msg` that corresponds to a branch in the `update`
function's `case` statement, which sends the user’s input to `HTTP.get` via
`buildSearchedPokemonResponse`. In there, if their input matches a Pokemon,
information will come back about that Pokemon. If not, they will get an error
message. For reference, here's the `update` function mentioned above:

```elm
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        RandomButtonClicked ->
            ( Loading
            , Random.generate ReceiveRandomId generateRandomNumber
            )

        ReceiveRandomId id ->
            ( Loading, pokemonRequestById id )

        ReceivePokemonResponse result ->
            case result of
                Ok pokemon ->
                    ( SuccessWithPokemon pokemon, Cmd.none )

                Err _ ->
                    ( Failure, Cmd.none )

        UserTypedInName name ->
            ( Loading, pokemonRequestByName name )
```

Of all the features I had planned for this app, I thought this one would take me
the longest. However, with the way the Elm architecture is built, it took me
about 2 minutes to wire everything up. Here is the `search` function in the
`view` section of my app:

```elm
search : String -> Html Msg
search query =
    div [ class "lines__header-wrapper" ]
        [ div [ class "search__wrapper" ]
            [ input
                [ placeholder "Search for a Pokemon"
                , type_ "search"
                , value query
                , onInput UserTypedInName
                ]
                []
            ]
        ]
```

For first-time Elm users, writing your HTML using Elm’s [HTML
library](https://package.elm-lang.org/packages/elm/html/latest/) is definitely a
bit strange, but doing so allows you to extract your view to different, smaller
blocks (sort of like the way I broke down the decoders). You can swap in
different “views” to your main `view` function depending on what `Model` you
return in your `update` function. This allows you to conditionally render chunks
of your `view` code and encourages you to make reusable "components" for your
page ... sounds sorta like React, doesn’t it?

The difference between React and Elm, though, is that Elm's reusable components
are actually just functions! React seems to be [heading in this
direction](https://medium.com/@andrea.chiarelli/the-functional-side-of-react-229bdb26d9a6),
but it's not as strict as Elm (yet) — components in React can still be
classes that extend `Component`. However, in Elm, you _extract_ reusable code
_only_ into functions - since Elm is a functional programming language from the
ground up, unlike JavaScript/TypeScript.

You can also add CSS to your app, either by rolling your own stylesheet and just
popping it into the `index.html` file like you would in basic webpages, or you
can use one of Elm’s CSS packages to manage everything for you. I just rolled my
own since styling wasn’t my main focus here, but
[`elm-css`](https://package.elm-lang.org/packages/rtfeldman/elm-css/latest/)
seems to be one of the more popular ones.

**TL;DR**: Elm basically has its own version of JSX and encourages you to
organize your `view` into components. This makes for a highly reusable and
organizable UI, which React developers will appreciate.

## Wrap Up

Elm is a language that is extremely conscious of first-time users. Getting up
and running in it is much less difficult compared to starting a project using
TypeScript - though Rails still takes the cake overall. In addition, I felt much
more comfortable dipping my toes into functional programming practices using
this language than a more abstract one like Scala. The added benefit of a
strictly typed system and a helpful compiler made me feel much more focused and
able to complete parts of my app faster.

Overall, there are a couple things to get used to when it comes to Elm. The
first and most important is the **architecture**. If you plan on doing a project
in Elm for the first time, I would read up on that to get an idea of what design
considerations Elm expects of you. As I’ve mentioned above, that was what took
me the longest to get used to. The other is **building decoders** - this is not
something you have to do in a Rails or even a TypeScript project. Though,
depending on how strict your settings are in the latter, you might add types to
the responses you receive from an API, which is one step closer to the kind of
work put into building an Elm decoder.

I would highly recommend anyone new to strictly typed languages or functional
programming to check out Elm as a way to build your first project. I found it a
joy to work with and I’m excited to do more with it.

**PS**: If you want to see the entirety of my project, you can visit the
[repo](https://github.com/ej-mitchell/pokedex). I’ve also created a
[gist](https://gist.github.com/ej-mitchell/8dc5d34cdaff356aea0ebd51b69b4810) with
all of the learning resources I’ve used / currently using. Have fun!
