[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-09-05 Thread Wouter In t Velt
After reading Josh Adams Time tracker SPA example something really clicked for 
me, and I feel I really "get it" now.
I did not know what I needed and how to ask for it, but this was extremely 
helpful, and got me back on track!

Also, I think my OP about the counters can be considered closed now. The guide 
has (recently) been updated with a great walk through of how to scale elm.

>From another thread (thanks to suttlecommakevin for sharing):
http://guide.elm-lang.org/reuse/

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-30 Thread Dmitry Utkin
Josh, this is great! Thanks for this idea

Textfield.onInput <| ProjectMsg' << SetNewProjectName



On Monday, August 29, 2016 at 11:03:12 PM UTC+3, Josh Adams wrote:
>
> Here's what I've been working on.  The recent git history is all about 
> refactoring.  Haven't introduced 'sub-components with state' or w/e and 
> don't see it coming soon.  It's an Elm-SPA with a Phoenix backend: 
> https://github.com/knewter/time-tracker
>
> On Monday, August 29, 2016 at 11:37:10 AM UTC-5, Rex van der Spuy wrote:
>>
>>
>>> For newcomers to Elm, *wouldn't it be better to change the scaling from 
>>> 1 to multiple counters in the guide in a different way? *
>>> E.g.
>>>
>>>1. Build everything in 1 module, e.g. save a copy of counter.elm as 
>>>counter-list.elm
>>>2. Change every building block (Model, Msg, update, view) one at a 
>>>time, and upgrade each to handle multiple counters
>>>   - Suggested order: Model, view, Msg, update
>>>3. After that, separate out the view (and only the view) of an 
>>>individual counter, with signature like "msg -> msg -> Int -> Html msg"
>>>   - with the two msg's being for increment and decrement
>>>
>>>
>>>
>> I would love to know how to do this!
>> Can anyone point me to a brain-dead-simple practical and working example 
>> for a non-expert Elm user like myself?
>>
>> I, like Wouter, have modelled all the Elm apps I've built over the last 9 
>> months on the counter-list example - commonly nesting 3 layers deep.
>>
>>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-30 Thread Erik Lott

>
> @Erik Lott, did you mean:
> view : Msg -> Msg -> Int -> Html Msg
> Or did I miss something?


Yeah, just a typo. Thanks for catching that. 

On Tuesday, August 30, 2016 at 5:27:06 AM UTC-4, Wouter In t Velt wrote:
>
> @Erik Lott, did you mean:
>
> view : Msg -> Msg -> Int -> Html Msg
>
> Or did I miss something?
>
> @Peter Damoc, yeah the flat solution would be simpler (I actually did do a 
> flat counter list before separating out the CounterView ;).
>
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-30 Thread Wouter In t Velt
@Erik Lott, did you mean:

view : Msg -> Msg -> Int -> Html Msg

Or did I miss something?

@Peter Damoc, yeah the flat solution would be simpler (I actually did do a flat 
counter list before separating out the CounterView ;).

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-29 Thread Erik Lott
Wouter, looks good. Yeah, it's not a big deal if the counter is nested or 
not in this case. Just one thought - I'm not sure that the generic 
signature of the CounterView.view is useful here:

view : msg -> msg -> Int -> Html msg

Yes, keeping the signature generic allows you to avoid importing Msg into 
this module, but it's better to use generic signatures when the function 
truly needs to accept generic arguments. In this case, you actually only 
ever plan to use a single incrementMsg (Increment) and single decrementMsg (
Decrement), so you might as well be specific:

view : Msg -> Msg -> Int -> Html msg

After that, you'll need to move CounterView.view into the main file with 
the rest of the code, or pull Msg into it's own file and import where 
needed.


On Monday, August 29, 2016 at 5:35:38 PM UTC-4, Wouter In t Velt wrote:
>
> I would love to know how to do this!
>> Can anyone point me to a brain-dead-simple practical and working example 
>> for a non-expert Elm user like myself?
>
> OK, so here is my take at an alternative multiple counters approach.
> {- Model needs to hold a list of counter values
> Any counter in the list is simply identified by its index
> -}
> type alias Model =
>   List CounterValue
>   
> type alias CounterValue =
>   Int
>
> -- the defaultmodel is simply an empty list
> defaultModel : Model
> defaultModel = 
>   []
>
> {- Original Msg type needs to be expanded to include the ID of the counter
> to update. So our update function knows which counter to change.
> We could have done something like a nested Msg structure.
> But no need to make things more complicated than needed, so we keep 
> things simple 
> -}
> type Msg =
>   AddCounter
>   | Increment CounterId
>   | Decrement CounterId
>   
> type alias CounterId =
>   Int
>
> {- Update uses helper function to update the right counter (indicated by 
> index from Msg)
> -}
> update : Msg -> Model -> Model
> update msg model =
>   case msg of
>
> AddCounter ->
>   -- add new counter with default value of zero to our list
>   model ++ [ 0 ]
>   
> Increment counterId ->
>   -- invoke helper to increment item at index
>   changeItemInList counterId (\item -> item + 1) model
>
> Decrement counterId ->
>   -- invoke helper to decrement item at index
>   changeItemInList counterId (\item -> item - 1) model
>
> -- helper to update an item in any list, applying a function to item at 
> index
> changeItemInList : Int -> (a -> a) -> List a -> List a
> changeItemInList idToUpdate itemUpdate someList =
>   List.indexedMap (setItemAtIndex idToUpdate itemUpdate) someList
>   
> -- apply itemUpdate function if index matches idToUpdate
> setItemAtIndex : Int -> (a -> a) -> Int -> a -> a
> setItemAtIndex idToUpdate itemUpdate index a =
>   if (idToUpdate == index) then
> itemUpdate a
>   else
> a
>
> {- view renders a button to add a counter + list of counters from model -}
> view : Model -> Html Msg
> view model =
>   let
> countersHtml =
>   List.indexedMap counterView model
>   in
> div []
>   [ button [ onClick AddCounter ] [ text "Add counter" ]
>   , div [ style [("display","flex")] ]
>   countersHtml
>   ]
>
> -- helper to render a counter, we need the index to include in message
> counterView : Int -> CounterValue -> Html Msg
> counterView index counterValue =
>   CounterView.view (Increment index) (Decrement index) counterValue
>
> A note here: Looping over the entire list of counters to update one 
> single counter, with the update helpers, feels inefficient. An alternative 
> is to use Dict, and get the item to update. But then each branch in the 
> update is around 10 instead of 1 line, because get returns a Maybe type, 
> and we have to factor this in.
>
> The separated CounterView.elm module is:
> module CounterView exposing (..)
> import Html exposing (Html)
>
> {- our view function takes 3 arguments:
>   1. some Increment message (of any type, therefore in lowercase)
>   2. some decrement message
>   3. an Int with the counter value to display
> The output is Html + the msg type of the 2 input messages.
> So our view function, and this module do not own the message type.
> Could have put the static parts (the 2 messages) in a config record, like 
> the elm-sortable-table,
> but for just 2 input variables, a record feels like overkill
> -}
> view : msg -> msg -> Int -> Html msg
> view incrementMsg decrementMsg counterValue =
>   div [ style [("flex","0 0 32px")]]
> [ button [ onClick incrementMsg ] [ text "+" ]
> , div [] [ text (toString counterValue) ]
> , button [ onClick decrementMsg ] [ text "-" ]
> ]
>
> Note here: The API of this view function is msg -> msg -> Int, so the 
> importing module needs to know to pass these three variables + what they 
> are supposed to do + what type they should be.
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this 

[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-29 Thread Erik Lott

>
> Here's what I've been working on.  The recent git history is all about 
> refactoring.  Haven't introduced 'sub-components with state' or w/e and 
> don't see it coming soon.  It's an Elm-SPA with a Phoenix backend: 
> https://github.com/knewter/time-tracker


Josh, make sure to share this example in the other threads. Clean spa 
examples like this will help other folks find their elm legs. Good stuff..

On Monday, August 29, 2016 at 4:03:12 PM UTC-4, Josh Adams wrote:
>
> Here's what I've been working on.  The recent git history is all about 
> refactoring.  Haven't introduced 'sub-components with state' or w/e and 
> don't see it coming soon.  It's an Elm-SPA with a Phoenix backend: 
> https://github.com/knewter/time-tracker
>
> On Monday, August 29, 2016 at 11:37:10 AM UTC-5, Rex van der Spuy wrote:
>>
>>
>>> For newcomers to Elm, *wouldn't it be better to change the scaling from 
>>> 1 to multiple counters in the guide in a different way? *
>>> E.g.
>>>
>>>1. Build everything in 1 module, e.g. save a copy of counter.elm as 
>>>counter-list.elm
>>>2. Change every building block (Model, Msg, update, view) one at a 
>>>time, and upgrade each to handle multiple counters
>>>   - Suggested order: Model, view, Msg, update
>>>3. After that, separate out the view (and only the view) of an 
>>>individual counter, with signature like "msg -> msg -> Int -> Html msg"
>>>   - with the two msg's being for increment and decrement
>>>
>>>
>>>
>> I would love to know how to do this!
>> Can anyone point me to a brain-dead-simple practical and working example 
>> for a non-expert Elm user like myself?
>>
>> I, like Wouter, have modelled all the Elm apps I've built over the last 9 
>> months on the counter-list example - commonly nesting 3 layers deep.
>>
>>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-29 Thread Wouter In t Velt

>
> Here's what I've been working on.  The recent git history is all about 
> refactoring.  Haven't introduced 'sub-components with state' or w/e and 
> don't see it coming soon.  It's an Elm-SPA with a Phoenix backend: 
> https://github.com/knewter/time-tracker
>

Looks interesting. Thanks for sharing!
First impression is that you have somehow managed to do stuff in about 1/10 
the amount of code I typically end up with.
I'll dive deeper to try and understand how you did that/ where my 
inefficiencies are!

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-29 Thread Wouter In t Velt

>
> I would love to know how to do this!
> Can anyone point me to a brain-dead-simple practical and working example 
> for a non-expert Elm user like myself?

OK, so here is my take at an alternative multiple counters approach.
{- Model needs to hold a list of counter values
Any counter in the list is simply identified by its index
-}
type alias Model =
  List CounterValue
  
type alias CounterValue =
  Int

-- the defaultmodel is simply an empty list
defaultModel : Model
defaultModel = 
  []

{- Original Msg type needs to be expanded to include the ID of the counter
to update. So our update function knows which counter to change.
We could have done something like a nested Msg structure.
But no need to make things more complicated than needed, so we keep things 
simple 
-}
type Msg =
  AddCounter
  | Increment CounterId
  | Decrement CounterId
  
type alias CounterId =
  Int

{- Update uses helper function to update the right counter (indicated by 
index from Msg)
-}
update : Msg -> Model -> Model
update msg model =
  case msg of

AddCounter ->
  -- add new counter with default value of zero to our list
  model ++ [ 0 ]
  
Increment counterId ->
  -- invoke helper to increment item at index
  changeItemInList counterId (\item -> item + 1) model

Decrement counterId ->
  -- invoke helper to decrement item at index
  changeItemInList counterId (\item -> item - 1) model

-- helper to update an item in any list, applying a function to item at 
index
changeItemInList : Int -> (a -> a) -> List a -> List a
changeItemInList idToUpdate itemUpdate someList =
  List.indexedMap (setItemAtIndex idToUpdate itemUpdate) someList
  
-- apply itemUpdate function if index matches idToUpdate
setItemAtIndex : Int -> (a -> a) -> Int -> a -> a
setItemAtIndex idToUpdate itemUpdate index a =
  if (idToUpdate == index) then
itemUpdate a
  else
a

{- view renders a button to add a counter + list of counters from model -}
view : Model -> Html Msg
view model =
  let
countersHtml =
  List.indexedMap counterView model
  in
div []
  [ button [ onClick AddCounter ] [ text "Add counter" ]
  , div [ style [("display","flex")] ]
  countersHtml
  ]

-- helper to render a counter, we need the index to include in message
counterView : Int -> CounterValue -> Html Msg
counterView index counterValue =
  CounterView.view (Increment index) (Decrement index) counterValue

A note here: Looping over the entire list of counters to update one single 
counter, with the update helpers, feels inefficient. An alternative is to 
use Dict, and get the item to update. But then each branch in the update is 
around 10 instead of 1 line, because get returns a Maybe type, and we have 
to factor this in.

The separated CounterView.elm module is:
module CounterView exposing (..)
import Html exposing (Html)

{- our view function takes 3 arguments:
  1. some Increment message (of any type, therefore in lowercase)
  2. some decrement message
  3. an Int with the counter value to display
The output is Html + the msg type of the 2 input messages.
So our view function, and this module do not own the message type.
Could have put the static parts (the 2 messages) in a config record, like 
the elm-sortable-table,
but for just 2 input variables, a record feels like overkill
-}
view : msg -> msg -> Int -> Html msg
view incrementMsg decrementMsg counterValue =
  div [ style [("flex","0 0 32px")]]
[ button [ onClick incrementMsg ] [ text "+" ]
, div [] [ text (toString counterValue) ]
, button [ onClick decrementMsg ] [ text "-" ]
]

Note here: The API of this view function is msg -> msg -> Int, so the 
importing module needs to know to pass these three variables + what they 
are supposed to do + what type they should be.

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-29 Thread Wouter In t Velt

>
> I would love to know how to do this!
> Can anyone point me to a brain-dead-simple practical and working example 
> for a non-expert Elm user like myself?

OK, so here is my take at an alternative multiple counters approach.
import Html exposing (Html, div, button, text)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (onClick)
import Html.Attributes exposing (style)
import CounterView -- our separated view function

main =
  beginnerProgram 
{ model = defaultModel
, view = view
, update = update 
}

{- Model needs to hold a list of counter values
Any counter in the list is simply identified by its index
-}
type alias Model =
  List CounterValue
  
type alias CounterValue =
  Int

-- the defaultmodel is simply an empty list
defaultModel : Model
defaultModel = 
  []

{- Original Msg type needs to be expanded to include the ID of the counter
to update. So our update function knows which counter to change.
We could have done something like a nested Msg structure:
type alias Msg =
  AddCounter
  | ForCounter CounterId CounterMsg
  
type alias CounterMsg =
  Increment
  | Decrement
  
But no need to make things more complicated than needed, so we keep things 
simple 
-}
type Msg =
  AddCounter
  | Increment CounterId
  | Decrement CounterId
  
type alias CounterId =
  Int

{- Update takes the message and update model (duh ;), 
using a helper function to update the right counter (indicated by index from 
Msg)
-}
update : Msg -> Model -> Model
update msg model =
  case msg of

AddCounter ->
  -- add new counter with default value of zero to our list
  model ++ [ 0 ]
  
Increment counterId ->
  -- invoke helper to increment item at index
  changeItemInList counterId (\item -> item + 1) model

Decrement counterId ->
  -- invoke helper to decrement item at index
  changeItemInList counterId (\item -> item - 1) model

-- helper to update an item in any list, applying a function to item at 
index
changeItemInList : Int -> (a -> a) -> List a -> List a
changeItemInList idToUpdate itemUpdate someList =
  List.indexedMap (setItemAtIndex idToUpdate itemUpdate) someList
  
-- apply itemUpdate function if index matches idToUpdate
setItemAtIndex : Int -> (a -> a) -> Int -> a -> a
setItemAtIndex idToUpdate itemUpdate index a =
  if (idToUpdate == index) then
itemUpdate a
  else
a

{- view renders a button to add a counter + list of counters from model -}
view : Model -> Html Msg
view model =
  let
countersHtml =
  List.indexedMap counterView model
  in
div []
  [ button [ onClick AddCounter ] [ text "Add counter" ]
  , div [ style [("display","flex")] ]
  countersHtml
  ]

-- helper to render a counter, we need the index to include in message
counterView : Int -> CounterValue -> Html Msg
counterView index counterValue =
  CounterView.view (Increment index) (Decrement index) counterValue

A note here: Looping over the entire list of counters to update one single 
counter, with the update helpers, feels inefficient. An alternative is to 
use Dict, and get the item to update. But then each branch in the update is 
around 10 instead of 1 line, because get returns a Maybe type, and we have 
to factor this in.

The separated CounterView.elm module is:
module CounterView exposing (..)
import Html exposing (Html)

{- our view function takes 3 arguments:
  1. some Increment message (of any type, therefore in lowercase)
  2. some decrement message
  3. an Int with the counter value to display
The output is Html + the msg type of the 2 input messages.
So our view function, and this module do not own the message type.
Could have put the static parts (the 2 messages) in a config record, like 
the elm-sortable-table,
but for just 2 input variables, a record feels like overkill
-}
view : msg -> msg -> Int -> Html msg
view incrementMsg decrementMsg counterValue =
  div [ style [("flex","0 0 32px")]]
[ button [ onClick incrementMsg ] [ text "+" ]
, div [] [ text (toString counterValue) ]
, button [ onClick decrementMsg ] [ text "-" ]
]

Note here: The API of this view function is msg -> msg -> Int, so the 
importing module needs to know to pass these three variables + what they 
are supposed to do + what type they should be.

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-29 Thread Wouter In t Velt

>
> I would love to know how to do this!
> Can anyone point me to a brain-dead-simple practical and working example 
> for a non-expert Elm user like myself?


OK, so here is my take at an alternative multiple counters approach.
First, putting everything in one (monolithic) module:

import Html exposing (Html, div, button, text)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (onClick)
import Html.Attributes exposing (style)

import CounterView -- our separated view function

main =
  beginnerProgram 
{ model = defaultModel
, view = view
, update = update 
}

{- Model needs to hold a list of counter values
For clarity, we define an alias for CounterValue
The uid of the original counter list Model is not really needed
Any counter in the list is simply identified by its index
-}
type alias Model =
  List CounterValue
  
type alias CounterValue =
  Int

-- the defaultmodel is simply an empty list
defaultModel : Model
defaultModel = 
  []

{- Original Msg type needs to be expanded to include the ID of the counter
to update. So our update function knows which counter to change.
We could have done something like a nested Msg structure:

type alias Msg =
  AddCounter
  | ForCounter CounterId CounterMsg
  
type alias CounterMsg =
  Increment
  | Decrement
  
But no need to make things more complicated than needed, so we keep things 
simple
-}
type Msg =
  AddCounter
  | Increment CounterId
  | Decrement CounterId
  
type alias CounterId =
  Int


{- Update takes the message and update model (duh ;), 
using a helper function to update the right counter (indicated by index from 
Msg)
in its list
-}
update : Msg -> Model -> Model
update msg model =
  case msg of

AddCounter ->
  -- add new counter with default value of zero to our list
  model ++ [ 0 ]
  
Increment counterId ->
  -- invoke helper to increment item at index
  changeItemInList counterId (\item -> item + 1) model

Decrement counterId ->
  -- invoke helper to decrement item at index
  changeItemInList counterId (\item -> item - 1) model


-- helper to update an item in any list, applying a function to item at 
index
changeItemInList : Int -> (a -> a) -> List a -> List a
changeItemInList idToUpdate itemUpdate someList =
  List.indexedMap (setItemAtIndex idToUpdate itemUpdate) someList
  
-- apply itemUpdate function if index matches idToUpdate
setItemAtIndex : Int -> (a -> a) -> Int -> a -> a
setItemAtIndex idToUpdate itemUpdate index a =
  if (idToUpdate == index) then
itemUpdate a
  else
a


{- view renders a button to add a counter + list of counters from model
-}
view : Model -> Html Msg
view model =
  let
countersHtml =
  List.indexedMap counterView model
  in
div []
  [ button [ onClick AddCounter ] [ text "Add counter" ]
  , div [ style [("display","flex")] ]
  countersHtml
  ]

-- helper to render a counter, we need the index to include in message
counterView : Int -> CounterValue -> Html Msg
counterView index counterValue =
  CounterView.view (Increment index) (Decrement index) counterValue

A note here:

   - Looping over the entire list of counters to update one single counter, 
   with the update helpers, feels inefficient. An alternative is to use Dict, 
   and get the item to update. But then each branch in the update is around 10 
   instead of 1 line, because get returns a Maybe type, and we have to factor 
   this in.

The separated CounterView.elm module is:
module CounterView exposing (..)

import Html exposing (Html)

{- our view function takes 3 arguments:
  1. some Increment message (of any type, therefore in lowercase)
  2. some decrement message
  3. an Int with the counter value to display

The output is Html + the msg type of the 2 input messages.
So our view function, and this module do not own the message type.

Could have put the static parts (the 2 messages) in a config record, like 
the elm-sortable-table,
but for just 2 input variables, a record feels like overkill
-}
view : msg -> msg -> Int -> Html msg
view incrementMsg decrementMsg counterValue =
  div [ style [("flex","0 0 32px")]]
[ button [ onClick incrementMsg ] [ text "+" ]
, div [] [ text (toString counterValue) ]
, button [ onClick decrementMsg ] [ text "-" ]
]


Note here:

   - The API of this view function is msg -> msg -> Int, so the importing 
   module needs to know to pass these three variables + what they are supposed 
   to do + what type they should be.
   

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-29 Thread Wouter In t Velt

>
> I would love to know how to do this!
> Can anyone point me to a brain-dead-simple practical and working example 
> for a non-expert Elm user like myself?


OK, so here is my take at an alternative multiple counters approach.
First, putting everything in one (monolithic) module:

import Html exposing (Html, div, button, text)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (onClick)
import Html.Attributes exposing (style)

main =
  beginnerProgram 
{ model = defaultModel
, view = view
, update = update 
}

{- Model needs to hold a list of counter values
For clarity, we define an alias for CounterValue
The uid of the original counter list Model is not really needed
Any counter in the list is simply identified by its index
-}
type alias Model =
  List CounterValue
  
type alias CounterValue =
  Int

-- the defaultmodel is simply an empty list
defaultModel : Model
defaultModel = 
  []

{- Original Msg type needs to be expanded to include the ID of the counter
to update. So our update function knows which counter to change.
We could have done something like a nested Msg structure:

type alias Msg =
  AddCounter
  | ForCounter CounterId CounterMsg
  
type alias CounterMsg =
  Increment
  | Decrement
  
But no need to make things more complicated than needed, so we keep things 
simple
-}
type Msg =
  AddCounter
  | Increment CounterId
  | Decrement CounterId
  
type alias CounterId =
  Int


{- Update takes the message and update model (duh ;), 
using a helper function to update the right counter (indicated by index from 
Msg)
in its list
-}
update : Msg -> Model -> Model
update msg model =
  case msg of

AddCounter ->
  -- add new counter with default value of zero to our list
  model ++ [ 0 ]
  
Increment counterId ->
  -- invoke helper to increment item at index
  changeItemInList counterId (\item -> item + 1) model

Decrement counterId ->
  -- invoke helper to decrement item at index
  changeItemInList counterId (\item -> item - 1) model


-- helper to update an item in any list, applying a function to item at 
index
changeItemInList : Int -> (a -> a) -> List a -> List a
changeItemInList idToUpdate itemUpdate someList =
  List.indexedMap (setItemAtIndex idToUpdate itemUpdate) someList
  
-- apply itemUpdate function if index matches idToUpdate
setItemAtIndex : Int -> (a -> a) -> Int -> a -> a
setItemAtIndex idToUpdate itemUpdate index a =
  if (idToUpdate == index) then
itemUpdate a
  else
a


{- view renders a button to add a counter + list of counters from model
-}
view : Model -> Html Msg
view model =
  let
countersHtml =
  List.indexedMap counterView model
  in
div []
  [ button [ onClick AddCounter ] [ text "Add counter" ]
  , div [ style [("display","flex")] ]
  countersHtml
  ]

-- helper to render a counter, we need the index to include in message
counterView : Int -> CounterValue -> Html Msg
counterView index counterValue =
  div [ style [("flex","0 0 32px")]]
[ button [ onClick (Increment index) ] [ text "+" ]
, div [] [ text (toString counterValue) ]
, button [ onClick (Decrement index) ] [ text "-" ]
]


A note here:

   - Looping over the entire list of counters to update one single counter, 
   with the update helpers, feels inefficient. An alternative is to use Dict, 
   and get the item to update. But then each branch in the update is around 10 
   instead of 1 line, because get returns a Maybe type, and we have to factor 
   this in.
   


I would do the separation of view function of an individual counter as 
follows:

The original module (as above) would only require 2 changes:

...
-- import our newly separated view function
import CounterView

...

-- the helper function is changed: we now call the view function on our 
imported module, and pass our Msg types + counter value
counterView : Int -> CounterValue -> Html Msg
counterView index counterValue =
  CounterView.view (Increment index) (Decrement index) counterValue


The separated CounterView.elm module is:
module CounterView exposing (..)

import Html exposing (Html)

{- our view function takes 3 arguments:
  1. some Increment message (of any type, therefore in lowercase)
  2. some decrement message
  3. an Int with the counter value to display

The output is Html + the msg type of the 2 input messages.
So our view function, and this module do not own the message type.

Could have put the static parts (the 2 messages) in a config record, like 
the elm-sortable-table,
but for just 2 input variables, a record feels like overkill
-}
view : msg -> msg -> Int -> Html msg
view incrementMsg decrementMsg counterValue =
  div [ style [("flex","0 0 32px")]]
[ button [ onClick incrementMsg ] [ text "+" ]
, div [] [ text (toString counterValue) ]
, button [ onClick decrementMsg ] [ text "-" ]
]


Note here:

   - The API of this view function is msg -> msg -> 

[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-29 Thread Rex van der Spuy

>
>
> For newcomers to Elm, *wouldn't it be better to change the scaling from 1 
> to multiple counters in the guide in a different way? *
> E.g.
>
>1. Build everything in 1 module, e.g. save a copy of counter.elm as 
>counter-list.elm
>2. Change every building block (Model, Msg, update, view) one at a 
>time, and upgrade each to handle multiple counters
>   - Suggested order: Model, view, Msg, update
>3. After that, separate out the view (and only the view) of an 
>individual counter, with signature like "msg -> msg -> Int -> Html msg"
>   - with the two msg's being for increment and decrement
>
>
>
I would love to know how to do this!
Can anyone point me to a brain-dead-simple practical and working example 
for a non-expert Elm user like myself?

I, like Wouter, have modelled all the Elm apps I've built over the last 9 
months on the counter-list example - commonly nesting 3 layers deep.

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-28 Thread Erik Lott

>
> It's like I keep falling whenever I try to ride this new elm-bike. 
> And I keep hearing from others that they just get up and go and don't fall,
> so I should also just go and don't fall, or be very specific at which 
> point in my process I fall off my bike.
> (Sorry if the analogy is somewhat far fetched).


That's an honest reply. I certainly did not have this effortless learning 
experience. I've been programming applications for a long time, and Elm 
made me feel like a noob again. Very very humbling. 

Back in the days, when I learned react, I found this page 
> 
>  very 
> helpful. It explains how to structure in react. What state is, and where to 
> put it.
> Maybe a similar "thinking in elm" page will 
> a) help folks like me learn how to structure their apps in elm and 
> b) reduce unwanted/ vague questions about components on this forum.


+10 agree. I think at this point, its becoming obvious that there needs to 
be a more thorough "on-ramp" post(s) to ease folks' minds' into "thinking 
in elm". Without that, it's like the wild west - everyone is trying to 
figure out how to structure an app, and the only thing they can reach for 
is previous mental models - React folks try to apply react ideas to elm; 
Angular people try to apply angular ideas to elm, etc.. 

On Sunday, August 28, 2016 at 5:43:11 PM UTC-4, Wouter In t Velt wrote:
>
> Thanks for the feedback folks. Really helpful and got me thinking. Will 
> definitely dive into the links @NickH shared.
> And @ErikLott's example of a multi-page SPA (forgive the oxymoron) was 
> also helpful. This is one of the places I run into issues: my top level 
> update is already huge and growing.
>
> Also, I take the advice to heart to share/ ask questions on concrete and 
> practical cases.
>
> That said, for me, scaling Elm remains a struggle, and I find it hard to 
> pinpoint specific use cases to share here as a question.
>
> I really believe it when more experienced people say that elm scales, I am 
> just struggling with the "how".
>
> It's like I keep falling whenever I try to ride this new elm-bike. 
> And I keep hearing from others that they just get up and go and don't fall,
> so I should also just go and don't fall, or be very specific at which 
> point in my process I fall off my bike.
> (Sorry if the analogy is somewhat far fetched).
>
> This was different when I learned react some years ago.
> And I was just wondering why it was such a different experience.
>
> And it occurred to me that some of the "why does everyone insist on asking 
> about components"-meme may have been triggered because the counter example 
> is a very prominent (if not the most prominent) example in the Guide.
>
> I agree with Nick H that adding more examples is probably more helpful 
> than rewriting existing ones. 
>
> Back in the days, when I learned react, I found this page 
>  very 
> helpful. It explains how to structure in react. What state is, and where to 
> put it.
> Maybe a similar "thinking in elm" page will 
> a) help folks like me learn how to structure their apps in elm and 
> b) reduce unwanted/ vague questions about components on this forum.
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-28 Thread Mark Hamburg
One thing that might help in a Thinking in Elm context would be to put more 
emphasis on hierarchical model construction and hierarchical view construction 
as separate ideas. The latter is mostly about breaking things down via 
functions. The former is about defining data types and functions on those types 
and then combining those types to form larger types.

I don't know how well this would work if then followed with a building an Elm 
Architecture app where we then need to wire the pieces together with messages 
and an update function, but it might make the stay flat approach easier to 
sustain if it were focused on messages and the update function.

Mark

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-28 Thread Wouter In t Velt
Thanks for the feedback folks. Really helpful and got me thinking. Will 
definitely dive into the links @NickH shared.
And @ErikLott's example of a multi-page SPA (forgive the oxymoron) was also 
helpful. This is one of the places I run into issues: my top level update 
is already huge and growing.

Also, I take the advice to heart to share/ ask questions on concrete and 
practical cases.

That said, for me, scaling Elm remains a struggle, and I find it hard to 
pinpoint specific use cases to share here as a question.

I really believe it when more experienced people say that elm scales, I am 
just struggling with the "how".

It's like I keep falling whenever I try to ride this new elm-bike. 
And I keep hearing from others that they just get up and go and don't fall,
so I should also just go and don't fall, or be very specific at which point 
in my process I fall off my bike.
(Sorry if the analogy is somewhat far fetched).

This was different when I learned react some years ago.
And I was just wondering why it was such a different experience.

And it occurred to me that some of the "why does everyone insist on asking 
about components"-meme may have been triggered because the counter example 
is a very prominent (if not the most prominent) example in the Guide.

I agree with Nick H that adding more examples is probably more helpful than 
rewriting existing ones. 

Back in the days, when I learned react, I found this page 
 very 
helpful. It explains how to structure in react. What state is, and where to 
put it.
Maybe a similar "thinking in elm" page will 
a) help folks like me learn how to structure their apps in elm and 
b) reduce unwanted/ vague questions about components on this forum.

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-28 Thread Erik Lott
Folks, Elm scales just fine. We're at the tail-end of a large SPA front-end 
build in Elm... lots of complexity, and it's been wonderful.

The counter examples, sortable table, and autocomplete are fine examples of 
how to modularize elm code. They don't lead you down the wrong path, nor do 
they disagree with Richards advice to start simple (model/update/view). If 
you find this confusing, it just means you need to lay down a little more 
code first, and really internalize the simplicity of Elm... ultimately, 
regardless of how many modules you have, it's just functions all the way 
down, and a *single* state tree.

You won't build a large multipage app in a single module, nor does Richard 
ever promote that idea. You DO need to create modules to separate your app 
into pieces of functionality, and I'm not talking about Model, Update 
andView module (although you might decide to do this). The Counter module 
is a good example of a concept that has been pulled into a module - the 
fact that it is nested or not doesn't matter - it's just a module with an 
API, nothing more.

Here is a very basic primer showing how you might structure an imaginary 
SPA app:

Top Level

Page 1
Page 2 
Page 3
Page 4


Top Level
- Model hold the business/domain data tree for the entire app, the 
'currentPage', and the 'currentUser' (if you have to deal with auth).
- View uses the "currentPage" state to decide which page to display. 
- View passes slices of domain/business data to the Page.view function 
(Page models do not hold business/domain data)

Page Level
- Model hold page related state (this page section is open, this page 
section is closed, this form is submitting, etc).
- Page may provide an api, so that specific events that occur inside the 
page can be responded by outside code (The top level might take some action 
when the form on a Page has been submitted).

In all honesty, our app is not exactly arranged like this, but this 
imaginary example should be enough for people to ask questions about. How 
do I build this? How do I build that? Specific questions like this are so 
much easier to answer than "Does elm scale".


 


On Sunday, August 28, 2016 at 7:02:04 AM UTC-4, Wouter In t Velt wrote:
>
> Something I have been struggling with for quite some time (coming from 
> React and Flux) is how to scale. There are various posts on this forum 
> related to the topic, e.g. Design of large elm apps 
> , parent 
> child communication 
> ,
>  
> components 
> 
> .
>
> On structuring apps, I found the elm-sortable-table and the autocomplete 
> video - shared by Peter Damoc in this thread 
>  - 
> to be very helpful, as well as advice here 
> .
>
> My summary of the advice is more or less:
>
>- Forget about about "components": the term is very confusing, means 
>very different things in different contexts.
>- Start to build with 1 Model, 1 Msg, 1 update, 1 view
>- As soon as one these becomes too big, seperate that one out to a 
>view-helper, or update-helper etc
>
> This very much feels like a "top-down"  approach: the module you start 
> with remains on top. Put everything in there, and split out if needed.
> I keep reminding myself to stop trying to keep pieces of each of the 4 
> building blocks (Model, Msg, update, view) bundled as I separate out. That 
> it is fine to e.g. just put a piece of view code in a separate place - 
> *without 
> trying to bundle it with corresponding pieces of Model, Msg, and update.*
>
> Now I am not sure that my take on "how to do stuff"  is the right way, but 
> it does seem that the *multiple-counters example in the guide teach us 
> exactly the opposite pattern*. 
> *Do the multiple counter examples in the guide put us on the wrong foot?*
>
> We start out with one counter being the top module, and then we add a 
> wrapper *on top* to handle multiple instances of this counter.
> To make matters worse: the multiple counter examples introduces the kind 
> of opaque nesting and messaging structure that is being discouraged here:
> The parent does not know anything about each child counter, parent has its 
> own Msg structure etc.
> After scaling, the counter now has in effect become something that looks 
> and smells very much like a component.
>
> Just the other day I realized that much of my struggle with scaling came 
> from stuff I picked up on day 1 of learning Elm, with sinful thoughts such 
> as:
> "Hey, this counter thing in Elm is just like a reusable UI element. Just 
> like a react component, with state and all. 

[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-28 Thread Eric G

On Sunday, August 28, 2016 at 7:02:04 AM UTC-4, Wouter In t Velt wrote:
>
>
>- Forget about about "components": the term is very confusing, means 
>very different things in different contexts.
>- Start to build with 1 Model, 1 Msg, 1 update, 1 view
>- As soon as one these becomes too big, seperate that one out to a 
>view-helper, or update-helper etc
>
> This very much feels like a "top-down"  approach: the module you start 
> with remains on top. Put everything in there, and split out if needed.
>
>  
On the question about starting from one module and how to split it out, 
etc., I entirely agree with Richard's practical advice on this. But I am 
curious about people's Elm habits on a more micro level. When you say you 
feel it's "top down" to start with one module at the top, it got me 
thinking about this. 

Until recently, I found I had a tendency to want to build from the top, and 
got stuck on things like "I can't start until I figure out client-side 
routing [sic]". And when working on any particular piece of the app, I 
wanted to completely implement it down through all the descendants. And I 
did it in a particular order: Model and update, make sure that compiles, 
and then view, and then updates involving side effects, and associated view 
changes. I started to notice this approach was causing extra work. By the 
time I got to the view, inevitably I would have forgotten a particular 
update, or needed some state I hadn't accounted for, or realized it was 
better to split the state between modules differently, etc. And that would 
set off another round of changes, all before I even had something to play 
around with in the browser. It was taking way too long to get visual 
feedback. 

It seems obvious in retrospect, but I have switched to a "bottom-up" style 
that prioritizes getting visual feedback: (1) build only the piece of my 
app I need feedback on; (2) don't implement every view and action from the 
start, leave placeholders, especially for pieces of the UI that may be 
variants of each other; (3) start from the view and work up to the model 
and update based on what you need at that particular stage; (4) hard code 
external data and bring it in through `Task.succeed`, `Task.fromMaybe "not 
found" Dict.get` and similar; (5) style it initially in the browser.

I usually have a very basic Main that inits the piece of the app I'm 
working on, and I serve that up fullscreen on a "demo page", to fiddle with 
and eventually to show stakeholders. So far it's working well for me, as 
long as I stay focused on getting something up ASAP, however incomplete.

Curious what other people's practices are like.

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-28 Thread Dmitry Utkin
Hi

On Sunday, August 28, 2016 at 2:02:04 PM UTC+3, Wouter In t Velt wrote:
>
> Something I have been struggling with for quite some time (coming from 
> React and Flux) is how to scale. There are various posts on this forum 
> related to the topic, e.g. Design of large elm apps 
> , parent 
> child communication 
> ,
>  
> components 
> 
> .
>

I'm struggling with this also, like most of us does. All of the approaches 
I've stumbled upon so far have their issues unfortunately.


> On structuring apps, I found the elm-sortable-table and the autocomplete 
> video - shared by Peter Damoc in this thread 
>  - 
> to be very helpful, as well as advice here 
> .
>
> My summary of the advice is more or less:
>
>- Forget about about "components": the term is very confusing, means 
>very different things in different contexts.
>- Start to build with 1 Model, 1 Msg, 1 update, 1 view
>- As soon as one these becomes too big, seperate that one out to a 
>view-helper, or update-helper etc
>
> This very much feels like a "top-down"  approach: the module you start 
> with remains on top. Put everything in there, and split out if needed.
> I keep reminding myself to stop trying to keep pieces of each of the 4 
> building blocks (Model, Msg, update, view) bundled as I separate out. That 
> it is fine to e.g. just put a piece of view code in a separate place - 
> *without 
> trying to bundle it with corresponding pieces of Model, Msg, and update.*
>

I'm not sure why all this `let's not call components "components"` thing 
started recently. I thinks it's perfectly fine to think in the terms of 
`components`, `widgets`, parent-, child- and all that stuff. Almost 
anything on a webpage can be named as a component, having child components 
and a parent component. It's natural to group and name those things this 
way, imho. Context matters, of course and it's OK.

The issue we have with terminology is `stateful components`(in OOP terms) 
vs `stateless components`. In React world, this is an issue since React 
components implemented as classes can contain state.
Elm nature tells us that there's not such thing as a `stateful Elm 
component`. So we always use this term without being misinterpreted - great!

So in the Elm world, component is a piece of code that
1) takes some props\params\input
2) generates html as a visible output to the input given
3) pipes the user-generated events up to the appropriate handler

In pre-0.17 world we had an easy way to pass the handler(signal address) 
down by providing some context to the `view` like this 

 
The simplest thing, like passing a callback in JS.
But nowadays(if we're going the fully-featured component path), we need to 
handle all of the events by generating a Msg, handling that Msg inside the 
`update` function of the component and then just return some kind of 
`OutMsg`(or `Dispatch` or `Whatever`) up to the parent.
If parent is not interested in this kind of event, but knows that his 
parent IS, it has to still has to convert it to some `ParentOutMsg` and 
bubble up the event to it's parent. Now *this* is the real issue that 
brings ideas like `stay flat for as long as you can` to life, imho.
 

>
> Now I am not sure that my take on "how to do stuff"  is the right way, but 
> it does seem that the *multiple-counters example in the guide teach us 
> exactly the opposite pattern*. 
> *Do the multiple counter examples in the guide put us on the wrong foot?*
>

Still waiting on this page 
 of the guide 
to update. Maybe Evan will come up with a nicer way to handle the wiring 
and Elm apps could be claimed to scale up easily.
I don't think the examples are bad because I'm not sold on the `stay flat` 
or `start flat` and the best argument against that idea is how clear and 
self-contained Conter.elm 

 is, 
and how easily it's being reused in two different apps in the `/nesting` 
folder.
 

>
> We start out with one counter being the top module, and then we add a 
> wrapper *on top* to handle multiple instances of this counter.
> To make matters worse: the multiple counter examples introduces the kind 
> of opaque nesting and messaging structure that is being discouraged here:
> The parent does not know anything about each child counter, parent has its 
> own Msg structure etc.
> After 

[elm-discuss] Re: Do the counters in the Guide teach us a wrong scaling approach?

2016-08-28 Thread Eric G
My take on it is - the standard "counter" examples are used not just in Elm 
but in lots of virtual-dom-based frameworks, I used to hate them as well 
but now I see their usefulness as a "Short, Self Contained, Correct 
Example" in which the domain has been reduced to the bare minimum. And I 
have to say I found the progression from counter -> pair of counters -> 
list of counters was instructive and sticks with me -- even if it wasn't 
the only way I learned Elm.  But beyond the basic mechanics of updating 
nested state, it doesn't get you very far.  

Part of the challenge with tutorials built around "realistic examples" I 
think is that people look at the final code and are tempted to think that's 
a model for how to start out, when of course it's a whole organic process 
with many many decisions behind how the code got to that point, and what 
makes sense in that case may not in another.

I am very glad we have the videos (and code) from those code sessions now 
to study, but my understanding is they are focused on building reusable 
components and specifically on the interface between those components and 
your app (have not looked at them yet myself so I could be wrong). This 
seems different to me from structuring your app's modules.  

In your app, any given parent references child Model, init, update, view, 
and sometimes Msg directly, and there are well-worn paths for doing this, 
made quite easy with Html.App.map, as well as emerging conventions for 
passing back messages to the parent from the child (OutMsg, etc.). 

For components on the other hand, the interface has to be worked out in 
terms of what the component hides from your app, and there are different 
approaches.  So I don't see the process of app development as aiming at 
'decoupling' your whole app into components, that seems to add complexity 
where it's not needed.

(That said, there are times when I have done things like what you suggest 
with the counter subviews -- parameterized them by passing in msg or msg 
constructors -- when I have two variants that are otherwise identical. I 
always feel dirty doing that though and try to keep that to a private view 
function close to where it's called. )


On Sunday, August 28, 2016 at 7:02:04 AM UTC-4, Wouter In t Velt wrote:
>
> Something I have been struggling with for quite some time (coming from 
> React and Flux) is how to scale. There are various posts on this forum 
> related to the topic, e.g. Design of large elm apps 
> , parent 
> child communication 
> ,
>  
> components 
> 
> .
>
> On structuring apps, I found the elm-sortable-table and the autocomplete 
> video - shared by Peter Damoc in this thread 
>  - 
> to be very helpful, as well as advice here 
> .
>
> My summary of the advice is more or less:
>
>- Forget about about "components": the term is very confusing, means 
>very different things in different contexts.
>- Start to build with 1 Model, 1 Msg, 1 update, 1 view
>- As soon as one these becomes too big, seperate that one out to a 
>view-helper, or update-helper etc
>
> This very much feels like a "top-down"  approach: the module you start 
> with remains on top. Put everything in there, and split out if needed.
> I keep reminding myself to stop trying to keep pieces of each of the 4 
> building blocks (Model, Msg, update, view) bundled as I separate out. That 
> it is fine to e.g. just put a piece of view code in a separate place - 
> *without 
> trying to bundle it with corresponding pieces of Model, Msg, and update.*
>
> Now I am not sure that my take on "how to do stuff"  is the right way, but 
> it does seem that the *multiple-counters example in the guide teach us 
> exactly the opposite pattern*. 
> *Do the multiple counter examples in the guide put us on the wrong foot?*
>
> We start out with one counter being the top module, and then we add a 
> wrapper *on top* to handle multiple instances of this counter.
> To make matters worse: the multiple counter examples introduces the kind 
> of opaque nesting and messaging structure that is being discouraged here:
> The parent does not know anything about each child counter, parent has its 
> own Msg structure etc.
> After scaling, the counter now has in effect become something that looks 
> and smells very much like a component.
>
> Just the other day I realized that much of my struggle with scaling came 
> from stuff I picked up on day 1 of learning Elm, with sinful thoughts such 
> as:
> "Hey, this counter thing in Elm is just like a reusable UI