Trying your luck with Elm
Tags: elm, functional, webdev, tutorial
Published: 2022-03-20 20:50:35

## Contents
  * [Boilerplate](#boilerplate)
  * [Baby Steps and Generators](#baby-steps)
  * [Look at my dice, my dice is amazing!](#my-dice)
  * [Roll the Dice](#roll)
  * [Final Considerations](#considerations)
  * [TL:DR](#tldr)

---

Some time ago I was going through interviews for multiple companies and as pretty much every developer, I've been through some weird but also some funny and thoughtful ones.

This one was on the thoughtful side and gave me some considerations while also confirmed thoughts I had from a time where I was the one interviewing.

The test was really simple;
> "Implement a web app that rolls a dice with a button click and show the face with the correct number to the user."

As you can see, nothing that complex but it was funny to implement in Elm and I thought it might be good to share it for the sake of describing step by step my implementation for anyone who's trying to grasp a little bit more about the language.

## Boilerplate I guess... <a name="boilerplate"></a>

The first thing would be prepare the boilerplate. I won't assume you have any previous experience with Elm, will try my best to explain my thought process here from the ground up, let's go from the most basic steps then.

```ELM
module Main exposing (..)

import Browser
import Html exposing (..)
Import Random

-- MAIN


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

-- MODEL


type alias Model = {}


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

-- UPDATE


type Msg = NoOp


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        NoOp ->
            (model, Cmd.none)

-- SUBSCRIPTIONS


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


view : Model -> Html Msg
view _ =
    div [] [text "Hello World"]
        
```

Dissecting the boilerplate we have a `main` as the entry point that calls the `init` function with a `Model` that is just a empty Record that will be passed to the `view` function which will only render a `div` element with a `Hello World` text as its content.


## Baby Steps and Generators <a name="baby-steps"></a>

Now that we have the boilerplate let's continue with baby steps.

- _How will we think about implementing this "dice face randomizer"?._

Well, I tend to think towards
_Behavior -> Visualization | UI -> Polishing_ and I'll be following those steps.

- _But what can we consider as behavior?_

I see "generate a random number within a button click" as the basic behavior of this problem. We can implement this with a [Generator](https://package.elm-lang.org/packages/elm/random/latest/Random#Generator).

In Elm you cannot call a `Math.random` the same way you can call in Javascript. It is a non deterministic behavior and as such it should be correctly handled by Elm in a slightly different way to achieve what we want. Taking a look on the documentation for the `Random` module it's possible to see the example below that encapsulates pretty much what we need to do.

```ELM
type Msg = NewNumber Int

newNumber : Cmd Msg
newNumber =
  Random.generate NewNumber oneToTen
```

- _But what does this example says exactly?._

It says that you can call a `Random.generate` with two arguments, a function that returns a `Msg` type and a `Generator` of some type so it can return a `Cmd Msg` for you. Regarding the type annotations and the basics of how it works I think the [documentation](https://package.elm-lang.org/packages/elm/random/1.0.0/Random) can explain it better than I'll ever be able to so please take a look for more in depth details.

We know from the documentation that `Random.generate` can create a `Cmd Msg` for us but we don't have anything useful for that in our `Msg` type yet, so, lets implement it to receive a randomized number:

```ELM
type Msg =
  Rolled Int

oneToSix : Random.Generator Int
oneToSix = Random.int 1 6
```

Now we have a useful `Msg` but that's not enough, as you might remember the `Random.Generator` we have here is not something we can attach to our `Msg` type. It will not work since `Rolled` receives an `Int` and `oneToSix` is of type `Random.Generator Int`.

This `oneToSix` generator need to be called to really _"generate"_ the value. That's a side effect and for that we need to ask Elm to perform it for us. So, now we need to use the `Random.generate` to generate a `Cmd` that Elm will gladly perform.

```ELM
rollDice : Cmd Msg
rollDice = Random.generate Rolled oneToSix
```

That's nice, now we have a `Cmd` that Elm can perform and pass the value to our `Msg` type which will gladly update our number. Update? Do we have this update logic in place? I don't think so...

```ELM
init : () -> ( Model, Cmd Msg )
init _ =
    ( Model 1, Cmd.none )

...

type alias Model = { value : Int }

...

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Rolled newValue ->
            ({ model | value = newValue }, Cmd.none)
```

- _Now I think we're covered. Our `init` function was updated to initialize the `Model` with a default value of `1`, the `Model` is holding a value to be rendered and the `update` function is receiving the `newValue` which will be generated by the `rollDice` command right?_

Unfortunately not. Since `rollDice` is a command we need a way to trigger that and say "Hey Elm, perform this action for me".

If we look closely to the `update` function we can see that it returns a tuple with `( Model, Cmd Msg )`, the type signature for our `rollDice` is a `Cmd Msg`.

- _Why not put this here on our `update` function since that's the way Elm transitioning from one model state to the other? Should I put that on the `Rolled` scope?_

Put the `rollDice` command in the returned tuple from the `Rolled` Msg will trigger, every time this message have been triggered, the `rollDice` command. But `rollDice` calls `Rolled` and it will create a loop that freezes your application.

The correct way is to create a second `Msg` that will say "Hey Elm, call `rollDice` to me". That way the `Random.generate` can call the `Rolled` without creating a loop within our `update`.

```ELM

type Msg
  = Rolled Int
  | NewNumber

...

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Rolled newValue ->
            ({ model | value = newValue }, Cmd.none)

        NewNumber ->
            (model, rollDice)
```

Now the only missing piece is to be able to click a button to generate this number and see the number on the screen.

```ELM
view : Model -> Html Msg
view { value } =
    div []
      [ span [] [ text (String.fromInt value) ]
      , br [] []
      , button [ onClick NewNumber ] [ text "Randomize" ]
      ]
```

Here we need to use `String.fromInt` since the type of the `value` variable is `Int` and the `Html.text` function receives a `String`.

You can click [here](https://ellie-app.com/gVTgNfKcVFba1) to check the app till this point.

## Look at my dice, my dice is amazing! <a name="my-dice"></a>

Now that we have our generator in place and we can see that it is working, it's time to start to move from the abstract behavior to the more concrete idea of a dice.

> A dice face is made of dots and spaces between those dots.

That's not so helpful isn't it? We need a way to check how those dots are distributed for each one of the its faces. Just like this next picture.

![Dice faces](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s6s5r8d7jrt3ie44n9il.jpeg) 

Now that's helpful. We can see that the dots have a distribution that is possible to be described as lines and columns. The best way to visualize that is as if we had a Rubik's cube where every single face is white and we can paint black some of the pieces that compose each face to describe one of the dice faces.

Thats a good metaphor but you have to understand that it is mostly a description of a 3x3 matrix (Same as each single face of the Rubik's cube) and following that we will implement a matrix representation using lists to render our amazing dice.

```ELM
renderDot : Bool -> Html Msg
renderDot visible =
    let
        dotClass = 
          if visible then
              "dot"
          else
              "dot__invisible"
    in
    div [ class dotClass ] []

view : Model -> Html Msg
view { value } =
    let
        renderRow lst =
            lst
                |> List.map renderDot
                |> div [ class "dots-row" ]

        rows =
            [ [ True, False, True ]
            , [ True, False, True ]
            , [ True, False, True ]
            ]
                |> List.map renderRow

        renderDice _ =
            div [ class "dice-container" ]
                [ rows |> div [ class "dice" ]
                ]
    in
    div [ class "main" ]
        [ renderDice value
        , div [ class "button-container" ] [ button [ onClick NewNumber ] [ text "Roll The Dice" ] ]
        ]
```
Here we're creating a really simple `renderDot` function that receives a boolean flag and if its `True` the dot will be rendered as a black spot otherwise it will be rendered as transparent so we can have the correct spacing between dots.

The `view` function got a little more weird but isn't that complex. We have a `main` div and inside that we have two containers. First one holding the `renderDice` function that returns a `Html Msg` and thus a valid children. The second container holds the button to roll the dice.

Within the `let...in` scope we have:

- `renderDice`: A function that receives an argument but currently ignores it and return a `Html Msg`, our `dice-container` with the `dice` as its direct children.
- `rows`: A value that calls `renderRow` passing a representation of a 3x3 matrix.
- `renderRow`: A function that receives a list of boolean flag and maps every element to our `renderDot` function creating at the end a list of `Html Msg`. In that case a row containing a representation of three dots.

You can check the current state of the implementation and the whole CSS necessary to render the UI [here](https://ellie-app.com/gYKMSTVc6NDa1). Please take your time to understand if needed.

## Roll the Dice <a name="roll"></a>

The missing piece right now is connect our current functions in a way that we can check which number renders which face.

Lets firstly check what we already have that could be useful so we don't get lost within multiple moving parts.

Do you recall our `renderRow` function and our `rows` value? Let's move then out of the `let...in` scope so we can re-use them to build the rows automatically for us.

```ELM
generateDotsFromMatrix : List (List Bool) -> Html Msg
generateDotsFromMatrix matrix =
    let
        generateDotsRow list =
            list
                |> List.map generateDot
                |> div [ class "dots-row" ]
    in
    matrix
        |> List.map generateDotsLine
        |> div [ class "dice__content" ]
```

Now we have changed our previous `rows` value to a `generateDotsFromMatrix`, a function that receives our matrix representation and returns the content of the dice. We also renamed the `renderRow` function to `generateDotsRow` which describes what the function does in a more clear way and renamed `renderDot` function to `generateDot` for the same reason. 

That's it, only a matter of grounding some moving parts to ease our transition to a more reusable logic.

- _What about the other faces? This dice only renders one face..._

You're right, let's fix that.

```ELM
renderDice value =
    let
        dots =
            case value of
                1 ->
                    generateTruesFromMatrix 
                        [ [ False, False, False ]
                        , [ False, True, False ]
                        , [ False, False, False ]
                        ]

                2 ->
                    generateTruesFromMatrix 
                        [ [True, False, False]
                        , [ False, False, False ]
                        , [ False, False, True ]
                        ]

                3 ->
                    generateTruesFromMatrix
                        [ [ True, False, False ]
                        , [ False, True, False ]
                        , [ False, False, True ]
                        ]

                4 ->
                    generateTruesFromMatrix 
                        [ [ True, False, True ]
                        , [ False, False, False ]
                        , [ True, False, True ]
                        ]

                5 ->
                    generateTruesFromMatrix
                        [ [ True, False, True ]
                        , [ False, True, False ]
                        , [ True, False, True ]
                        ]

                _ ->
                    generateTruesFromMatrix 
                        [ [ True, False, True ]
                        , [ True, False, True ]
                        , [ True, False, True ]
                        ]
    in
    div [ class "dice-container" ]
        [ div [ class "dice" ] [ dots ]
        ]


view : Model -> Html Msg
view { value } =
    div [ class "main" ]
        [ renderDice value
        , div [ class "button-container" ] [ button [ onClick NewNumber ] [ text "Roll The Dice" ] ]
        ]
```

Updating our function `renderDice`, using pattern match to map from all the possible given values to the correct matrix that represents the combination of black and transparent dots for a given dice face.

- _That's it, right, a fully fledged "Roll the dice" app!!._

Yeah, if you only consider what was asked for, that's it.

But what if, for some reason, someone touches your `renderDice` function and changed some flags. Will be hard to track those changes just by looking at it right?. A flag doesn't mean anything by itself we can just change the `renderDot` function to do the opposite and voila all the app logic breaks and we will not understand easily because only the `if...else` was swapped and that's why using those boolean flags isn't a good idea. It's time to do some changes in order to keep us sane if we ever need to touch this code again.

```ELM
type Dot 
  = Dot
  | Placeholder 

...

generateDot : Dot -> Html Msg
generateDot mDot =
    let
        cls =
            case mDot of
                Dot ->
                    "dot"
                Placeholder ->
                    "dot__invisible"
    in
    div [ class cls ] []

generateDotsFromMatrix : List (List Dot) -> Html Msg
-- Implementation remains untouched...
```

Created a `Dot` custom type that better fits the domain of the problem and did small updates in the `generateDot` function and in the type annotation of the `generateDotsFromMatrix` function.

The last change is at our `renderDice` function, we'll change every occurrence of `True` to `Dot` and `False` to `Placeholder` that way we can easily understand if some of the faces have something weird going on later.

That's a small change but with a big impact on how we handle our code since using this custom type helps on understand what is being rendered for each part of the face representation and catch any weird logic change.

```ELM
-- Easy, the matrix that corresponds to 2.
[ [Dot, Placeholder, Placeholder]
, [ Placeholder, Placeholder, Placeholder ]
, [ Placeholder, Placeholder, Dot ] 
]
```

I know that everyone who's worked with Elm at a higher degree than pet projects will say that custom type should be considered and implemented from the start but I'm showing how my thought process was during this small challenge which had a specific time to finish while also trying to keep it easy to digest for people who are not really used to code with the language.

[Here's the Full App](https://ellie-app.com/gYMvyFk84pna1).

## Final Considerations <a name="considerations"></a>

The group of people whose interviewed me was really thoughtful and easy going. They not only gave me the whole boilerplate to start with but also let me consult the documentation and even _Stack Overflow_ if I wanted to. That's something that most technical interviews, at least that I've been through, tend to prevent you from doing. 

_But isn't that what we do, daily, as programmers?_ Check documentation, search for syntax specifics and sometimes understand how to do something through the experience of others. It should not be taken away just to see if you can hold a bunch of information that can be easily searched throughout internet. Our job should be based on problem solving not to try and hold a ginormous amount of information in our heads.

Throughout the interview the whole group was also really supportive and interactive, helping me not wander so much with the implementation details so I wouldn't throw curve balls to handle later. That's also something that a number of technical interviewers tend not to do. They see themselves as spectators, not interviewers. Pretend that they can't help you because if they do its like "cheating" but that's not the case and it's really good to see that whoever is interviewing you isn't just a static judge but a fellow developer who's capable of discuss and help you to build a better mindset for the problem while also preventing you to go down some unnecessary rabbit holes. That's what's expected from a good pair programming and what I think most interviewees want from a technical interview. _They also want to be hired but that's a whole different conversation..._

My final consideration is that you don't need complex problems to access someone's expertise and if you're an interviewer, you don't need to be a static judge. Strive to be someone that answer questions, pair programming and help the interviewee to feel heard and ease their concerns. I bet you can learn a bunch from them and vice-versa. Just be a fellow developer and enjoy the possibility to get to know a bunch of other developers with different backgrounds and experiences.

---

##TLDR <a name="tldr"></a>

_A pretty simple but funny technical interview challenge with minor details that enable the interviewers to grasp the experience level of the interviewee with the language.
[Full implementation](https://ellie-app.com/gYMvyFk84pna1)_