-
-
Save Janiczek/056d40574548df9cfb86 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Signal exposing (Signal, Address) | |
import Html exposing (Html, div, button, text) | |
import Html.Events exposing (onClick) | |
-- There would normally be "import StartApp.Simple as StartApp exposing (start) | |
-- but for learning purposes we roll our own at the bottom. | |
-- Check it out after grasping this Counter example! | |
-- Our Counter will | |
-- 1. display a number | |
-- 2. let the user increment it | |
-- 3. let the user decrement it | |
main : Signal Html -- The entry point to the whole app. We need a Signal (think of it as of a stream) of Html | |
main = | |
start { model = model | |
, view = view | |
, update = update } | |
type alias Model = Int -- Our data is just a number. | |
model : Model -- Initial value | |
model = 0 | |
view : Address Action -> Model -> Html -- Each HTML element has a list of Attributes and a list of children. | |
view address model = | |
div [] | |
[ button [ onClick address Decrement ] [ text "-" ] | |
, div [] [ text (toString model) ] | |
, button [ onClick address Increment ] [ text "+" ] | |
] | |
type Action = Increment -- Our high-level descriptions of what can happen to the model. | |
| Decrement -- We could for example add a Reset action, Double action, etc... | |
update : Action -> Model -> Model -- What happens to the model with each action? | |
update action model = -- We could clean our update fn and refactor these | |
case action of -- to eg. `Increment -> updateIncrement model` | |
Increment -> model + 1 -- where `updateIncrement model = model + 1`. | |
Decrement -> model - 1 -- Equational reasoning FTW! | |
----------------------------------------------------------- | |
-- StartApp | |
----------------------------------------------------------- | |
type alias App model action = -- What do we want from the user. | |
{ model : model | |
, view : Address action -> model -> Html | |
, update : action -> model -> model | |
} | |
start : App Model Action -> Signal Html -- The goal is to give a Signal (stream) of Html to the browser. | |
start app = | |
let | |
actions : Signal.Mailbox (Maybe Action) -- we create a mailbox (has an .address where we can Signal.send, and .signal) | |
actions = -- there will be Actions flowing eventually, | |
Signal.mailbox Nothing -- but at first there is no value. (type Maybe a = Nothing | Just a) | |
address : Signal.Address Action -- we don't want the user | |
address = -- to have to wrap his Actions in Just | |
Signal.forwardTo actions.address Just -- so this is where we do that automatically for him | |
step : Maybe Action -> Model -> Model -- again, don't make the user | |
step action model = -- unwrap the Maybe Action in his `update` function | |
case action of -- he doesn't have to know about any of this! | |
Nothing -> model | |
Just action' -> app.update action' model | |
model : Signal Model -- finally, the Big Loop (TM) | |
model = | |
Signal.foldp -- this is basically a `reduce` | |
step -- function | |
app.model -- initial value | |
actions.signal -- where to take values from | |
in | |
Signal.map (app.view address) model -- Signal Model becomes Signal Html | |
----------------------------------------------------------- | |
-- End StartApp | |
----------------------------------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment