Some of the best YouTube videos on Elm

During the course of learning Elm, I came across some excellent YouTube videos worth watching. I will keep updating this list as I find good videos

Advertisements

Working with backend services in Elm

Before we go past building trivial solution, we need to understand one more concept in trivial example scenario. How do we go about making backend calls? More preciously how to connect and work with API calls.

We will start out with looking at the final result and then we will go about building them. We are building a very simple application which will show the current market value of bitcoin. When you start the application you will see the following screen

image

The screen shows the the initial data of 0. On pressing ‘Get Data’ button, the application will make an API call to “https://api.cryptonator.com/api/ticker/ltc-usd”  url, and display the result as it is in the screen.

image

It does not show the value instead it just displays the whole JSON payload as it is. For our API call discussion we do not need to worry about how to parse JSON and other things, which we will discuss at a later time.

(It will be interesting to come back after couple of years and check the value of bitcoin again 🙂 )

Let’s start building the application without api call first to get the basic screen shown.

First Model:

type alias Model =
     { rate : String
     }

initData : Model
initData =
     { rate = “0”
     }

We have just one field in the model record, which we kept is as String for the sake of simplicity.

To get started we create the update section with

type Msg
     = GetData

update : Msg -> Model -> Model
update msg model =
     case msg of
         GetData ->
             dummyData

As you can expect, when a user clicks ‘GetData’, the GetData message fired by html. That is the only event we needed for the application right now. The action event on GetData does nothing but return a dummy data. It is not making a API call yet.

View is simple and straight forward. One label to show the rates and another button which initiates the GetData message.

view : Model -> Html Msg
view model =
     div []
         [ h3 [] [ text (“Current rate = ” ++ model.rate) ]
         , button [ onClick GetData ] [ text “Get Data” ]
         ]

main =
     Html.beginnerProgram { model = initData, view = view, update = update }

When you run the code first time, it will show the init data with 0.

image

On clicking GetData, it shows the dummy data as expected.

image

You can find the whole base code here in the Gist.

Time to add API call. There is one concept in here will look odd but it is easy to understand. Before we go to API call, I want to go one more time how html and our code interact.

view: Model –> Html Msg

update: Msg –> Model –> Model

In the above code snippet, the view takes the model and creates Html which is capable of creating Msgs (like onClick or onInput). What goes in creating the message is hidden inside the Html module and we do need to worry about, all we need to know is, when some user action happens, Msg will be triggered and ‘update’ function will be called immediately to act on it. 

Now the same way, let’s think about API call, when we make API call we need to wait for the call to complete and up on  completion, we need to modify the model and change in the model will update the view. Very simple. One difference between the button click event and the API event is that when API is called, there is a possibility the call might fail. So the result could come back as either successful (Ok resultValue) and the value or it could comeback with Error (Err _) with error message. So we need to handle both the scenarios in the code on completion of the API call.

Let’s recap what we discussed so far

  • We need to treat API call similar to Html event calls
  • We need a mechanism to fire a message on completion of API call
  • On completion we need to test for successful execution of API and error scenario

It seems there is a lot but not really. Let’s take baby steps and grasp the concept. To make API calls we need to install Http module. Once installed let’s write the code to make the API call. To make a Http Get we can use

Http.getString uri

this will make a call and gets string response from the uri. Simple. We could create a function which does it. But we have a problem, this return string and we need to wait for it complete. We need to modify this some how so that, on completion it generates a message which we can act on when we get it. How do we go about doing it?

It is solved by Http.send function. Http.send function, will return a message on completion of a http request. So we can modify the previous statement to something like the following

Http.send HttpDataComplete (Http.getString url)

Http.Send is a command, which will initiate the Http.getString and on completion it will trigger HttpDataComplete event/msg. So if we were to write a function to do this task it will be something like this

httpGetData: Cmd Msg

httpGetData which does not get any input data will generate a command which is capable of generating messages. Now let’s look at the implementation

httpGetData =

     Http.send HttpDataComplete (Http.getString “https://api.cryptonator.com/api/ticker/ltc-usd”)

We have a function to get data. Now we need to call this function when Get Data button pressed.

Our current update function signature is

update: Msg –> Model –> Model

This reads, update function takes Msg and current state of the model and generate new model. But the changes we made, when some one presses GetData button, we not only generate model but also create a command which could create msg (like out view defintion view : Model –> Html Msg). So our update definition now changes to

update: Msg –> Model –> (Model, Cmd Msg)

With that definition, when a user clicks on ‘GetData’, we need to call the httpGetData function. We will do it something like the following

case msg of

     GetData –>

            (model, httpGetData)

if you look at the return state here, it following the signature of (Model, Cmd Msg).  Now that we made the call how are we going to handle the response from get data call?

When you make a API call, you can get either a success or failure. On success, we change the rate value with result value. On failure, we need to reset it to initial data. In Elm we have something Result which helps with this situation. Anytime when we perform an operation which could result in success or failure then we need to use Result. With that, when Http make HttpDataComplete message, it will come back with result. So we need to modify the signature of our message to represent this scenario

HttpDataComplete (Result Http.Error string)

Now in our update function, when we get HttpDataComplete, we need to check for success and failure in the case

case msg of

     HttpDataComplete (Ok data) –>

     HttpDataComplete (Err _) –>

The second (Err _) parameter means, when you get an error with any value perform that function.

Now we know we need to handle both the scenario, what should be do when API calls comes back successful? All we need to do is modify the rate value in the model with incoming data. Now if you remember, our update function expect the second parameter to a command generating function. In our case after updating the model, we do not need to initiate any commands so all we need to pass is Cmd.none. On error reset the data model to initial data and same as success scenario, pass is no commands. So here is the completed update function

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
     case msg of
         GetData ->
             ( model, httpGetData )

        HttpDataComplete (Ok val) ->
             ( { model | rate = val }, Cmd.none )

        HttpDataComplete (Err _) ->
             ( initData, Cmd.none )

We are not done yet, two more things we need to do. When we move to this model of program, it is possible you might want to load data from backend API on page load that means we need to call that function without any program intervention. To accomplish that, we need to move to a different helper function called ‘program’ in Html.

Html.program takes different set of parameters

  • First parameter is initial data. It includes the initial model and any function that need to be executed to load data from back end. In this example, we are not expecting to load any data from API on load. So the values (model, Cmd.none)
  • Second is view and there are no changes to it
  • Third parameter is update function. No change there.
  • Final parameter is subscription. For Http example there are no subscription so we are going to create a dummy subscription to satisfy the signature in a minute

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

You can find the final source code for this here in this Gist.

Basic debugging in Elm

This blog purely focus on very basic debugging. No time travel or anything fancy. Simple debugging features.

We will start with our baisc code which takes first name and last name in two different input field and when user pressed ‘FullName’ button, it displays the firstname + lastname in Full Name: label.

image

The program I started out is here in the Gist. With that code, when you run the application and enter the first name and last name like the following

image
and press FullName, you get the following result

 image

The last name is missing and the first name is added twice. (It is easy to fix but for the sake of debugging, we will continue as if we do not know the reasons).  So how do we go about debugging in the Elm?

For starters, when you run the elm in elm-reactor mode, the application runs in debug mode. When the application running in the browers, you will see small box at the bottom right hand side of the screen something like the following

image

If you click to open the window you will see two sections

One on the left, shows all the events that triggered. The one on the right side shows the current state of the model.

image

This will be great means to see all the events that get fired and also for each event how the model changes.

The second approach is the age old logging. Elm provides a mean to log messages to the browser console. We will start with the first problem, that is, the result of first name and last name shows first name twice.

We have following code for Add message

Add ->
           { model
               | fullName = model.firstName ++ model.firstName
               , firstName = “”
               , lastName = “”
           }

even though it is very clear that, we are adding firstName field twice, for the sake of showing logging, we will add logs. To add logs in Elm, you need to import Debug package, which is already part of the Core package you have installed.

1. Import Debug

2. Add log messages to see what is the value of the two fields we are adding

Adding log is pretty simple and very original. Before adding the log the Add event function was

Add ->

{ model

| fullName = model.firstName ++ model.firstName

, firstName = “”

, lastName = “”

}

To log you do not need to create a seperate line statement. You can do it inline like the following

Add ->
     { model
         | fullName = (log “first name : ” model.firstName) ++ (log “last name : ” model.firstName)
         , firstName = “”
         , lastName = “”
     }

Log function take two parameters, first one is string message and second parameter can be anything. Here is an interesting thing, in elm when you have log statement like this, log function logs the message but the underlying function (the original) executes normally. So in reality, the before and after program statement is same.

Open the developer console and execute the code and you will see the first and last name both are first name. So looking at the code we know the insted of adding the last name we were adding the first name.

image

Change the first name field to last name and run the code with the log and now we get different message. Instead of repeating the first name twice, now it displays only the first name and not the last name.

image

You can find the code with logs here in this Gist. Now let’s look why are we not getting the last name. We are going to use, time trave/history tab to see what is happening.  When a user enters a value in the input, for every keystroke onInput event fired. So let’s start there. We need to check and see if appropriate action event fired.

Based on the update event,

type Msg
     = Add
     | Clear
     | InputFN String
     | InputLN String

We expect InputLN event fired. Let’s open the tab and monitor the events.

First I typed ‘unni’ and you can see blow, InputFN fired for each keystroke and when I clicked FullName, you can see the Add event fired as well.

image

With this much information first thing we need to do is to check, do we have the view wired up properly to fire the events on data entry.

, input [ onInput InputFN ] []
, input [] []

The error is obvious, for the second input box, we do not have an onInput event.

Adding the onInput and running the code gives the expected answer.

image

This is the first stab at the debugging in Elm. You can find the final version of code here in this Gist.

Working with Input Fields in Elm

Continuing on the ‘SayMyName/Say Hello’ example, we will examine the input tag to understand the events and state management. Like other examples, let’s look at the final output first

image
We have added a new button ‘Clear’. When someone clicks clear button, it will clears the value in the input tag. 

Like other examples, we will start from the Model. There is no difference between the previous example model and this one.

type alias Model =
     { name : String
     , inputValue : String
     }

initData : Model
initData =
     { name = “”
     , inputValue = “”
     }

Next Update. Like we discussed in the previous blog, update has two parts, one to define a message associated with an action and second, execution or acting on action.

Defining the action:

type Msg
     = SayMyName
     | InputData String
     | Clear

We added the last message ‘Clear’ to our valid actions. Next we need to act on it. If and when someone presses the clear button, what we need is to clear the value of the input box. ‘inputValue’ holds the current value of the input box, so in our action execution, all we have to do is to set it to empty string. Something like the following

update : Msg -> Model -> Model
update msg model =
     case msg of
         SayMyName ->
             { model | name = model.inputValue, inputValue = “” }

        InputData val ->
             { model | inputValue = val }

        Clear ->
             { model | inputValue = “” }

The last two lines were added to clear the input value.

Finally view, in view we have to do two things;

  1. Define new Clear button and onClick we send out ‘Clear’ event. That is achieved through following definition in view

, button [ onClick Clear ] [ text “Clear” ]

2. When a user clicks the clear button our update function clears the value of inputValue in the model. To reflect the current value of the model, we have to set the value of the input box to model’s inputValue like the following

, input [ onInput InputData, value model.inputValue ] []

You can find full code here at this Gist.

Unit testing in Elm

Elm shines in help build applications which does not crash in production.  With static typing, functional nature and compile time verification the odds of breaking Elm application is low. That is been said, it does not give you pass not to write tests. I talked in length over time about TDD and why TDD is the best way to build applications. Here are two important things you need to know about TDD

  1. Help build highly maintainable code because the tests guarantee you will not break any other part of the application.
  2. TDD when done right, will allow you to write very little code to meet the expectation of the requirements. Less code you write less bugs you introduce.

Since everything in Elm is function, we can test everything.

To setup, we need to install elm-test package by running

elm package install elm-community/elm-test

This will install all the packages required for building unit tests. Once install, let’s initialize project structure for creating unit tests by running following in application root directory

elm-test init

This will create a test folder and create a simple test with a ‘todo’ and install associated project dependencies. So before you do anything, run

elm-test

in the root directory and it should run the default tests and come back with following message

elm-test 0.18.8
—————

Running 1 test. To reproduce these results, run: elm-test –fuzz 100 –seed 5741
56140

TEST RUN INCOMPLETE because there is 1 TODO remaining

If you get the above message then all setup and ready to start write testing. If you have problem setting up the test environment, send me a message.

I love to do my tests using BDD model and fortunately, there is a package for that which makes it very readable. When ‘elm-test init’ ran it created a sub directory called test to write all your tests. Switch to the test directory and install the BDD package

elm package install rogeriochaves/elm-test-bdd-style

Let’s get our feet wet with nothing fancy but just do normal assertions to see how they all connected. Create a a file in test subdirectory of the project root directory. Create an elm file, I called it ‘SayMyNameTester.elm”

Let’s start importing the required packages for testing

import Test exposing (..)
import Expect exposing (..)
import ElmTestBDDStyle exposing (..)

basictest : Test
basictest =
     describe “Tests Basic Assertions”
         [ test “1. can test equal traditionally”
             (\() -> Expect.equal “test” “test”)
         , test “2. can test equal traditionally with infix” <|
             \() -> Expect.equal “test” “test”
         , it “3. can test equal with bdd with infix” <|
             expect “test” to equal “test”
         , it “4. can test equal with bdd more readable”
             (expect “test” to equal “test”)
         ]

The above test is nothing but doing a simple assertion and “test” equal to “test” which results in true. But it was written in four different ways to show different ways of writing it and pick the one you are comfortable with and go with it.

When you run Elm-Test at the project root directory, it will executes all the files in the test directory with Test/Suite function definitions. In our code we have just one function definition with Test signature, which is basictest.  So running the Elm-Test should result something like the following

image

Let’s walk through each of the tests to understand what is the different

Test 1:

test “1. can test equal traditionally”
             (\() -> Expect.equal “test” “test”)

For starters, test function, takes a string and an Assertions and return a Test. The first parameter is “1. can test equal traditionally” a string. The second parameter is the Assertions “(\() -> Expect.equal “test” “test”)” which returns a Bool. For the people who are coming from traditional programming language,

\() –>

represents an anonymous function. Also the second parameter is enclosed in () so that it gets executed to return Test result.

Test 2:

This is exactly same as Test 1 except we replaced the () with an infix notation backward pipe operator <| Backward pipe and forward pipe operator (|>) or interesting operators of the functional programming, which got its roots from Unix world. You can read more about it here.  For me this gives more readability than using (). When you compose lot of operations, when using () might make it bit hard to read. So I prefer to use pipe operator

Test 3 & 4:

Test 3 & 4 are similar variations of Test 1 & 2 except, 3 & 4 is written in BDD style. Compare to 1 & 2, 3 & 4 are readable.

My recommendation to use the BDD style option 3 for more readability. Especially when you are building large code base, help the people who are coming after to do their job easier by writing readable tests. They will thank you for doing it.

I was going to write how to write a unit test for our project but I found a great video of Andy Balaam, who walks through the whole unit testing. It is worth checking out.

Reference:

https://medium.com/@_rchaves_/testing-in-elm-93ad05ee1832

https://www.linkedin.com/pulse/single-page-web-apps-elm-part-three-testing-structure-kevin-greene

Continuing the read code – Finally the view

We are building a very simple application which does not do anything fancy so that we can focus on the fundamentals of Elm. In the past two blogs we looked at

  • Model
    • We talked about type alias to keep the code readable by defining the alias for the core data structure so that you do not need to define it every time when one need to define the function definition
    • We also need to define the initial state of the application as part of the model definition. The main reason we need this to make sure on page load, the view is rendered through the initial state of the application
  • Update
    • Compared to other programming model, we need to define all the actions that are going to happen in a given application by defining the message types by using Elm specific type (union type or traditional enumeration type)
    • We need to create a function which will then act on a given action by changing the current state to new state, which will then trigger view rendering by taking the current state of the application and build the modified DOM elements

Basically Model defined the initial state and data structure while Update create the current state of the application. With that what is left is to render the view.

Traditionally most of the frameworks uses HTML or a template to build the view. In Elm, a true functional programming language even rendering HTML view done through functional model. In Elm, every html tag is a function. Each of these functions takes two list of arguments. First one is all attributes and second is list of all its children.

Let’s look at the code which will render our HTML page and then we can deconstruct it

view: Model –> Html Msg

view model =

    div []

    [

        h3 [ ] [ text “Your name is: “ ++ model.name]

        , input  [ onInput Change

                      , value model.inputdata ] []

       , button [ onClick SayMyName ]

        [ text “Say My Name”]

    ]

Let’s go through this code.

view: Model –> Html Msg is the function definition of the view function. View function takes model as input and generate Html and Html which could create messages

The first function call in the view is div function. As stated before, first array of list represent the attributes and second array is the collection of its children.

image

As specified in the diagram above, the first array is empty, but the second array, has three children

image

So far we have defined the model, update and view. As mentioned in the theory part of the Elm, we need an entry point and plumping needed to connect all these three components. That entry point is main as defined below

main =
     beginnerProgram { model = initData, view = view, update = update }

For getting started, we will leverage a function called beginnerProgram function and pass in the initial state of the model, the view and update function. The beginnerProgram will trigger the following on load

  1. First initial state of the mode created by running initData
  2. View function will take initData and render the HTML DOM elements
  3. As the user enters data in the input field, Change event will be triggered.
  4. Update function is called every time appropriate events are triggered
  5. Update function will be called with Change function and it will pass in the current value of the input text
  6. Update function execute Change event, which does nothing put populate inputdata with the input box value
  7. When the user clicks SayMyName button, view will trigger SayMyName event
  8. Update function called again with SayMyName event
  9. Update function executes SayMyName code block, which creates new model with name being populated with inputdata and inputdata set to blank, which represents the current state of the application
  10. When ever model changes, view function get called with current state of the application and repeat step (2) and forward again

You can find the full code here at the Gist.

Continuing the real code – Let’s talk about update

We are working on building a real code after series of theory blogs. We are building a very simple application which allows a user to enter a name (any string) in the input box and when the user clicks the ‘Say My Name’ button it will display the name in ‘Your name is:’ label.

image

In the last blog, we looked the model component. In this blog we will look at the update component.

Think of update component as a controller in a normal MVC pattern. This part of the code listens for event changes and update the model accordingly. Once the model updated the view will be rendered again to show the event’s reaction.

Like I said previously, update component reacts to the events. Like model, update also has two components

  1. Define all the events that we are interested in listening
  2. Write code to perform tasks when an event happens

Based on the end state of the application, what are all the possible events that can occur in the application. The obvious first event will be some one clicking the button ‘Say My Name” and let’s name the event  ‘SayMyName’.  The second one will be, when ever a user enters something in the input box, data change event for the input box will be triggered. Let’s name the event as ‘InputChange’ event. That is about it.

Next question, how do we go about defining these events? In Elm you define these events with type like the following. We identified the two events and we just create a type with the two events.

type Msg = SayMyName | InputChange String

You might have question how do you define this named event and where do we define them? We will look at them when we discuss the View component in detail. For now, when someone clicks the “Say My Name” button, some how the ‘SayMyName’ message will be triggered in update section.

InputChange event definition though is little different. When someone click the button, all the framework does it to trigger an event. On the otherhand, when someone changes a value in the input field, a change event get triggered with the changed value. That is why, InputChange event defined with one String parameter.

Now that we defined the events, let’s look at what are we going to do when these events occur?

update: Msg –> Model –> Model

because Elm is static type, it is good to define the update function first.Based on the signature, update function takes the message (Msg) as first parameter, which also takes Model (current state of the application) as second parameter and at the end of the update function, it returns modified state of the application model (Model).

In the last blog we looked at the Model. In that, we identified the two required fields. One to display the name (name) and another one to hold the input data in the input field(inputdata). With that knowledge, when a user clicks the ‘Say My Name’ button, we need to do the following

  • Copy inputdata to name field
  • Reset the inputdata field to be empty (“”)

How do we do it in functional Elm? We need to take the incoming model and modify name and inputdata. The way you modify records in Elm as follows

{model | name = model.inputdata, inputdata = “”}

following the code model above, when there is a change to the input field, we need take the new value and put it in the inputdata field.

{ model | inputdata = val}

where the val is incoming value on data change. It will make sense in a bit when we look at the whole update function.

update msg model =

    case msg of

         SayMyName –>

               {model | name = model.inputdata, inputdata = “”}

         InputChange  val –>

                {model | inputdata = val }

Update function take two parameters, first is the event that triggers the update function and also the current state of the data (as model)

In Elm, we check what event was triggered by doing something similar to switch statements in other languages. If you look at the code, there are no return statements. In functional programming there are no explicit return statements instead the last statement is treated as return statement. In our update function definition, update function is supposed to return a model. If you look at the each of the case statement, both has just one line statement and both return new instance of the model with new data.

Next we will talk about view