This page covers Elm 0.18

Commands

In Elm, commands (Cmd) are how we tell the runtime to execute things that involve side effects. For example:

  • Generate a random number
  • Make an http request
  • Save something into local storage

A Cmd can be one or a collection of things to do. We use commands to gather all the things that need to happen and hand them to the runtime. Then the runtime will execute them and feed the results back to the application.

In other words, every function returns a value in a functional language such as Elm. Function side effects in the traditional sense are forbidden by the language design and Elm takes an alternative approach to modeling them. Essentially, a function returns a command value which names the desired effect. Due to the Elm architecture, the main Html.program we've been using is the ultimate recipient of this command value. The update method of the Html.program then contains the logic to execute the named command.

Let's try an example app using commands:

module Main exposing (..)

import Html exposing (Html, div, button, text, program)
import Html.Events exposing (onClick)
import Random


-- MODEL


type alias Model =
    Int


init : ( Model, Cmd Msg )
init =
    ( 1, Cmd.none )



-- MESSAGES


type Msg
    = Roll
    | OnResult Int



-- VIEW


view : Model -> Html Msg
view model =
    div []
        [ button [ onClick Roll ] [ text "Roll" ]
        , text (toString model)
        ]



-- UPDATE


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Roll ->
            ( model, Random.generate OnResult (Random.int 1 6) )

        OnResult res ->
            ( res, Cmd.none )



-- MAIN


main : Program Never Model Msg
main =
    program
        { init = init
        , view = view
        , update = update
        , subscriptions = (always Sub.none)
        }

If you run this application it will show a button that will generate a random number each time you click it.


Let's review the relevant parts:

Messages

type Msg
    = Roll
    | OnResult Int

We have two possible messages in our application. Roll for rolling a new number. OnResult for getting a generated number back from the Random library.

Update

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Roll ->
            ( model, Random.generate➊ OnResult (Random.int 1 6) )

        OnResult res ->
            ( res, Cmd.none )

Random.generate creates a command that will generate random numbers. This function requires the first argument to be a constructor for the message that will be fed back to our application. In this case our constructor is OnResult.

So when the command is run Elm will call OnResult with the generated number, producing OnResult 2 for example. Then Html.program will feed this message back to application.

In case you're wondering, OnResult res denotes a message, OnResult, containing an additional payload of information, the Integer 'res' in this case. This pattern is known as parameterized types.


In a bigger application with many nested components we can potentially send many commands at once to Html.program. Take this diagram for example:

Flow

Here we collect commands from three different levels. At the end we send all these commands to program to run.

results matching ""

    No results matching ""