I have been wanting to learn Elm for a while and as I mentioned in an earlier post (https://lancewicks.com/2020/06/21/exploring-the-elm-programming-language/) I have managed on the third attempt to do so.
In the previous post I built a simple toy that displayed SVG. This time I decided to build something more practical; a timer app for the 1-2-4-All way of meeting facilitation (http://www.liberatingstructures.com/1-1-2-4-all/).
This app required “time”, specifically a countdown timer. So, it was a good opportunity to explore subscriptions in Elm. In this app I decided also to experiment with the Elm-UI package; which brings all your layout into Elm and prevents having to do CSS magic!
Elm-UI worked pretty well; I really like the ideas in elm-ui and not having to worry about CSS and to have a design system to hand. I won’t lie, it’s still ugly black text on white background (my Perl heritage showing?)… but that is me not the language or package.
Elm-ui for me is great as modern CSS is complicated and I find Elm-ui easy, simple and sensible. Like Elm itself, the constraints seem a positive not a negative.
Another thing I like is that I have been following the “single file till you really need it” approach… and that is working well. I like having all the code in one place and at 223 (well spaced) lines it’s not even a large single file.
Being a more complicated application turned out to be helpful for my learning. I initially had a time subscription that was naive and just counted upwards. So then I simply hard coded the second thresholds to display the right text at the right time.
Later I re-wrote it. The nice thing about a typed language with an awesome compiler is that this was all pretty easy and safe. When I changed things the compiler would tell me when I needed to update something else.
The main logic looks like this:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Start ->
( { model | status = True }, Cmd.none ) |> Update.andThen update PhaseOne
Stop ->
( { model | status = False }, Cmd.none )
Restart ->
( { model | status = True }, Cmd.none )
PhaseOne ->
( { model | phase = "One", next = "Two", timer = 60 }, Cmd.none )
PhaseTwo ->
( { model | phase = "Two", next = "Four", timer = 120 }, Cmd.none )
PhaseFour ->
( { model | phase = "Four", next = "All", timer = 240 }, Cmd.none )
PhaseAll ->
( { model | phase = "All", next = "All", timer = 300 }, Cmd.none )
Tick _ ->
if model.status then
if model.timer > 0 then
( { model | timer = model.timer - 1 }, Cmd.none )
else
case model.next of
"Two" ->
( { model | timer = 1 }, Cmd.none ) |> Update.andThen update PhaseTwo
"Four" ->
( { model | timer = 1 }, Cmd.none ) |> Update.andThen update PhaseFour
"All" ->
( { model | timer = 1 }, Cmd.none ) |> Update.andThen update PhaseAll
_ ->
( model, Cmd.none )
else
( { model | timer = model.timer - 0 }
, Cmd.none
)
It’s I am sure, not very idiomatic; but it works and is I hope pretty understandable.
The full code is here: https://github.com/lancew/124all
You can play with it here: https://lancew.github.io/124all/
I was going to try and add a SVG clock or something like that to this app; but my interest is waning. Time to find a new puzzle to solve… I think rewriting https://www.judowrl.com/https://www.judowrl.com/ in Elm. It is a small application I wrote in Javascript some time ago.
This will mean obtaining data from an API and so forth; so it will I hope round out the areas I have not looked at yet.
Stay tuned, if you follow me on Scuttlebutt I post more regular “dev diary” type posts on there (Look in my https://lancewicks.com/contact/ page for more on how to reach me on SSB).
[Edit July 2, 2020: I changed the wording around the web page looking agly a little to highlight that it is me not creating a pretty layout; rather than the elm-ui tool not being able to. Thanks to Alex Korban for pointing out to me it was confusing… I’m looking forward to reading his/your Elm book that is loaded on my tablet. ]
Categories: Uncategorized