Atomic Counters in Elm
In Elm, we don’t have the concept of shared mutable state or goroutines. Instead, we’ll simulate the atomic counter behavior using the Elm architecture with a single state and update function. We’ll use the Random module to simulate concurrent updates.
import Browser
import Html exposing (Html, div, text)
import Random
import Task
-- MODEL
type alias Model =
{ counter : Int
}
init : () -> (Model, Cmd Msg)
init _ =
( { counter = 0 }
, generateUpdates
)
-- UPDATE
type Msg
= Increment
| Complete
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Increment ->
( { model | counter = model.counter + 1 }
, Cmd.none
)
Complete ->
( model
, Cmd.none
)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
-- VIEW
view : Model -> Html Msg
view model =
div []
[ text ("Counter: " ++ String.fromInt model.counter)
]
-- COMMANDS
generateUpdates : Cmd Msg
generateUpdates =
List.range 1 50
|> List.map (\_ -> generateThousandUpdates)
|> Cmd.batch
generateThousandUpdates : Cmd Msg
generateThousandUpdates =
List.range 1 1000
|> List.map (\_ -> Random.generate (\_ -> Increment) Random.bool)
|> Cmd.batch
|> Task.perform identity
-- MAIN
main : Program () Model Msg
main =
Browser.element
{ init = init
, update = update
, subscriptions = subscriptions
, view = view
}In this Elm program:
We define a
Modelwith a singlecounterfield.The
initfunction sets up the initial state and triggers the generation of updates.We have two types of messages:
Incrementto increase the counter andComplete(unused in this example but could be used for additional functionality).The
updatefunction handles theIncrementmessage by increasing the counter.The
viewfunction displays the current counter value.generateUpdatescreates 50 batches of 1000 random update commands, simulating the behavior of 50 goroutines each incrementing 1000 times.generateThousandUpdatescreates 1000 random update commands.The
mainfunction sets up the Elm application.
To run this program:
- Save it as
AtomicCounter.elm - Use the Elm compiler to compile it:
elm make AtomicCounter.elm - Open the resulting
index.htmlin a web browser
You should see the counter value displayed, which will be updated to 50,000 almost instantly due to the simulation of concurrent updates.
Note that this is not truly concurrent or atomic in the same way as the original example, but it demonstrates how you might approach a similar problem in Elm’s functional, single-state-tree model.