Porting my binary clock to Elm
Binary clock in Clojurescript/Om
About a year ago I was playing with Clojurescript and Om, and made a small binary clock with it. You can read the original blog post here.
A couple of ports were created, in Reagent, and in Hoplon. Check them out!
Porting the same application to different languages or libraries/frameworks is a neat idea: it gives you a way to reason about different solutions of a problem, together with their inherent advantages and disadvantages. The most famous app in this category is perhaps TodoMVC.
Surely it would be fun to port the binary clock to Elm!
Some Elm resources
I found the following links helpful.
Firstly, the final result can be watched here, and the complete code is found on Github.
module BinClock where import Graphics.Element (Element, container, midTop) import Html (..) import Html.Attributes (..) import Signal import Window import List import Bitwise import Time (..) import Date
The clock is made of cells. We have two kinds, the clock and the
legend. The clock cells,
cellCol, are empty, but have two different colors, if
the bit is lit or not. The legend cells,
cellVal, doesn’t have a background
color, but instead contains a digit.
cellCol : Bool -> Html cellCol bit = let color = if bit then "light" else "dark" in div [class ("cell" ++ " " ++ color)]  cellVal : Int -> Html cellVal digit = div [class "cell"] [text (toString digit)]
I kept the data representation pretty close to the Clojurescript
BitNum is a pair containing the digit it represents, and
a list of
Bool corresponding to the bit representation of the digit.
In turn, a
column takes a
BitNum and creates a list of cells for
the bit representation, wrapped up in html markup.
type alias BitNum = (Int, List Bool) column : BitNum -> Html column (digit, bits) = let cells = (List.map cellCol bits) ++ [cellVal digit] in div [class "col"] cells columns : List BitNum -> Html columns cs = let cols = List.map column cs in div [class "colpair"] cols legend : List Int -> Html legend digits = let cells = List.map cellVal digits in div [class "col legend"] cells
We also need some code to take numbers, get the decimal parts, and
BitNum’s out of them:
decimalParts : Int -> List Int decimalParts n = [n // 10, rem n 10] toBitNum : Int -> BitNum toBitNum n = let masks = List.map2 Bitwise.and [8, 4, 2, 1] (List.repeat 4 n) setp = \x -> x > 0 bits = List.map setp masks in (n, bits)
The main view conclude the markup part were we crank everything
together. It takes current
Time as input and uses all of our markup
parts to build the clock.
view : Time -> Html view t = let conv = \x -> x |> decimalParts |> (List.map toBitNum) d = Date.fromTime t cols = [Date.hour d, Date.minute d, Date.second d] |> List.map conv |> List.map columns in div  ([legend [8,4,2,1]] ++ cols)
I mostly borrowed the startup code from the TodoMVC example. Note that
the main signal is augmented with
Time, triggered every second.
main : Signal Element main = Signal.map2 scene (every second) Window.dimensions scene : Time -> (Int,Int) -> Element scene t (w,h) = container w h midTop (toElement w h (view t))
That’s all, I hope you liked it!
Ports in other languages?
Wouldn’t it be cool to have ports in Purescript or GHCJS? Or maybe Idris or Funscript for that matter? Maybe I will. Or maybe you will? Let me know in any case.
If you have any comments or feedback, send me an email or send me a message on Twitter @lexicallyscoped.
← Go Back