In http://guide.elm-lang.org/architecture/modularity/counter_pair.html, we are given an application that reuses the counter application that was converted into a module for the purpose of this tutorial.
We were asked to make a swap between the two instances of the counter. That was easy due to the nature of the updates that create a new version of the model each time instead of updating it. So, we just swapped the instances of the two counters in the update.
Later, we were asked to extend the counter to log some statistics, since the parent module was not using the model directly it was very easy for us to extend the model and implement the changes needed in the update and the view of the model. No signatures were changed and init was modified to initialize all statistics along with the value.
Parent Module (1-counter-pair.elm)
import Counter import Html exposing (Html, button, div, text) import Html.App as App import Html.Events exposing (onClick) main = App.beginnerProgram { model = init 0 0 , update = update , view = view } -- MODEL type alias Model = { topCounter : Counter.Model , bottomCounter : Counter.Model } init : Int -> Int -> Model init top bottom = { topCounter = Counter.init top , bottomCounter = Counter.init bottom } -- UPDATE type Msg = Reset | Top Counter.Msg | Bottom Counter.Msg | Swap update : Msg -> Model -> Model update message model = case message of Reset -> init 0 0 Top msg -> { model | topCounter = Counter.update msg model.topCounter } Bottom msg -> { model | bottomCounter = Counter.update msg model.bottomCounter } Swap -> { model | bottomCounter = model.topCounter, topCounter = model.bottomCounter } -- VIEW view : Model -> Html Msg view model = div [] [ App.map Top (Counter.view model.topCounter) , App.map Bottom (Counter.view model.bottomCounter) , button [ onClick Reset ] [ text "RESET" ] , button [ onClick Swap ] [ text "Swap" ] ]
Counter Module (Counter.elm)
module Counter exposing (Model, Msg, init, update, view) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) -- MODEL type alias Model = { count : Int , max' : Int , min' : Int , increment : Int , decrement : Int } init : Int -> Model init count = Model count 0 0 0 0 -- UPDATE type Msg = Increment | Decrement update : Msg -> Model -> Model update msg model = case msg of Increment -> { model | count = model.count + 1 , max' = Basics.max (model.count + 1) model.max' , increment = model.increment + 1 } Decrement -> { model | count = model.count - 1 , min' = Basics.min (model.count - 1) model.min' , decrement = model.decrement + 1 } -- VIEW view : Model -> Html Msg view model = div [] [ button [ onClick Decrement ] [ text "-" ] , div [ countStyle ] [ text (toString model.count) ] , button [ onClick Increment ] [ text "+" ] , div [] [ text ("Max " ++ (toString model.max')) ] , div [] [ text ("Min " ++ (toString model.min')) ] , div [] [ text ("Increment " ++ (toString model.increment)) ] , div [] [ text ("Decrement " ++ (toString model.decrement)) ] ] countStyle : Attribute msg countStyle = style [ ("font-size", "20px") , ("font-family", "monospace") , ("display", "inline-block") , ("width", "50px") , ("text-align", "center") ]
You can download the solution from here [download id=”1822″]
This post is also available in: Αγγλικα