Porting my binary clock to Elm

Want to discuss the content of this article? Join the conversation on Twitter!

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.

Elm

Elm is a functional programming languange, related to Haskell. It compiles down to Javascript and is intended for interactive applications. Specifically it builds heavily on the idea of Functional Reactive Programming.

Surely it would be fun to port the binary clock to Elm!

Some Elm resources

I found the following links helpful.

Walkthrough

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 original: a 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 create 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.