Hmm, I'd be curious if you could whip up a full compileable example, say a 
Multi-Counter project example we could paste into elm-try.  Perhaps mark 
things that are boilerplate and could be hoisted out to a parent library 
too so we can ignore those?  :-)


On Friday, August 12, 2016 at 12:15:20 PM UTC-6, Kasey Speakman wrote:
>
> Skimming through the code, it looks like batch commands will happen in 
> order. The mentioned `mailbox.push` was from the Elm source code.
>
> Also, I fleshed out an example with both a clean separation and using 
> event sourcing. I posted it with some commentary on marcosh's github 
> <https://github.com/marcosh/marcosh.github.io/issues/1>.
>
> I like the terminology in this example much better than my previous 
> examples, especially because `Action` was a previous concept in Elm.
>
> type Act = Increment | Decrement
>
> type Fact = Incremented Int | Decremented Int
>
> type Msg = Perform Act | Apply Fact
>
> perform : Act -> Model -> Cmd Msg
>
> apply : Fact -> Model -> Model
>
> update : Msg -> Model -> (Model, Cmd Msg)
> update msg model =
>   case msg of
>     Perform act ->
>       (model, perform act model)
>
>     Apply fact ->
>       (apply fact model, Cmd.none)
>
>
> The Facts here are also idempotent 
> <https://en.wikipedia.org/wiki/Idempotence> (no dependency on previous 
> values). That's not as important in this example, but can as its extended.
>
> On Friday, August 12, 2016 at 9:15:23 AM UTC-5, OvermindDL1 wrote:
>>
>> Will your pushed command appear after or before a potentially pushed 
>> 'other' command, say from an incoming port, or button click?  That is the 
>> part I am not sure about yet (not read enough Elm internals 'quite' yet).
>>
>> On Thursday, August 11, 2016 at 6:31:06 PM UTC-6, Kasey Speakman wrote:
>>>
>>> Checked the current implementation of Cmd.batch and it appears 
>>> sequential (`mailbox.push`). Ordering guarantees are not documented so I 
>>> suppose they shouldn't be depended on. But otherwise, the one I coded above 
>>> that guarantees Act doesn't change the model and Evt doesn't have effects 
>>> would work.
>>>
>>> On Thursday, August 11, 2016 at 6:33:39 PM UTC-5, Kasey Speakman wrote:
>>>>
>>>> Yes, that's why I said back to square one if Cmd.batch isn't ordered. 
>>>> The only thing this is guaranteeing (and the only intended guarantee) is 
>>>> that the messages which only update the model are separated from the ones 
>>>> which cause effects. The ones which cause effects produce ones which 
>>>> update 
>>>> the model, same as always.
>>>>
>>>> It occurs to me that some of the benefit of event sourcing the UI could 
>>>> be gained by adding features to the TTD, since it has the magic which 
>>>> ignores Cmds on replay. Some are already listed as ideas at 
>>>> http://debug.elm-lang.org/. I'd still have to keep the messages in my 
>>>> model and provide a way for the user to transmit them in a bug report. But 
>>>> if I could load them in the TTD, that would make repro a snap.
>>>>
>>>> On Thursday, August 11, 2016 at 5:22:05 PM UTC-5, OvermindDL1 wrote:
>>>>>
>>>>> Isn't `doSideEffects` basically just the current `update` function 
>>>>> though?  Except it is returning a list of changes (via message) to 
>>>>> perform 
>>>>> to a model instead of doing it in-place?  What is this saving precisely?
>>>>>
>>>>>
>>>>>
>>>>> On Thursday, August 11, 2016 at 4:05:57 PM UTC-6, Kasey Speakman wrote:
>>>>>>
>>>>>> Actually, I'd probably use a List instead of Maybe on the immediately 
>>>>>> returned event(s).
>>>>>>
>>>>>> doSideEffects : Act -> Model -> (List Evt, Cmd Evt)
>>>>>> doSideEffects act model = 
>>>>>>   case act of
>>>>>>     UpdateCustomer customer ->
>>>>>>       ( [ CustomerUpdateRequested ]
>>>>>>       , callServerWithCustomer customer
>>>>>>       )
>>>>>>
>>>>>>     ...
>>>>>>
>>>>>> updateModel : Evt -> Model -> Model
>>>>>>     ... -- implementation as previous
>>>>>>
>>>>>> update : Msg -> Model -> (Model, Cmd Msg)
>>>>>> update msg model =
>>>>>>   case msg of
>>>>>>     Action act ->
>>>>>>       let
>>>>>>         (events, command) = doSideEffects act model
>>>>>>       in
>>>>>>         (List.foldr updateModel model events, Cmd.map Evt command)
>>>>>>
>>>>>>     Event evt ->
>>>>>>       (updateModel evt model, Cmd.none)
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Thursday, August 11, 2016 at 4:26:03 PM UTC-5, Kasey Speakman 
>>>>>> wrote:
>>>>>>>
>>>>>>> Yes, that was the goal. That way the UI state is utterly 
>>>>>>> deterministic / reproducible in isolation of all outside services.
>>>>>>>
>>>>>>> That's a good point on the race conditions. I only use Cmd.batch 
>>>>>>> because it's the facility that came to mind. (I'm still getting 
>>>>>>> acquainted 
>>>>>>> with Elm.) I don't know if Cmd.batch makes any ordering guarantee.
>>>>>>>
>>>>>>> If not we'd be more or less back to square one. Abuse `update` to do 
>>>>>>> both things.
>>>>>>>
>>>>>>> doSideEffects: Act -> Model -> (Maybe Evt, Cmd Evt)
>>>>>>> doSideEffects act model =
>>>>>>>   case act of
>>>>>>>     UpdateCustomer customer ->
>>>>>>>       (Just CustomerUpdateRequested, callServerWithCustomer customer
>>>>>>> )
>>>>>>>
>>>>>>>     ...
>>>>>>>
>>>>>>> updateModel: Evt -> Model -> Model
>>>>>>> ... -- implementation as previous
>>>>>>>
>>>>>>> maybeUpdateModel:  Maybe Evt -> Model -> Model
>>>>>>> maybeUpdateModel evtOpt model =
>>>>>>>   case evtOpt of
>>>>>>>     Nothing ->
>>>>>>>       model
>>>>>>>
>>>>>>>     Just evt ->
>>>>>>>       updateModel evt model
>>>>>>>
>>>>>>> update : Msg -> Model -> (Model, Cmd Msg)
>>>>>>> update msg model =
>>>>>>>   case msg of
>>>>>>>     Action act ->
>>>>>>>       let
>>>>>>>         (eventNow, command) = doSideEffects act model
>>>>>>>       in
>>>>>>>         (maybeUpdateModel eventNow model, Cmd.map Evt command)
>>>>>>>
>>>>>>>     Event evt ->
>>>>>>>       (updateModel evt model, Cmd.none)
>>>>>>>
>>>>>>> So this should apply an event immediately if one is needed for the 
>>>>>>> action. But it still keeps the model updating events separate.
>>>>>>>
>>>>>>> These immediate events would be seen by a userland event-store 
>>>>>>> implementation (which is underneath updateModel), but I bet the TTD 
>>>>>>> wouldn't see it since it doesn't come from Elm.
>>>>>>>
>>>>>>> On Thursday, August 11, 2016 at 3:43:36 PM UTC-5, OvermindDL1 wrote:
>>>>>>>>
>>>>>>>> So you really are wanting to hard device events into two different 
>>>>>>>> ones, those that can *only* alter the model, and those that can *only* 
>>>>>>>> send 
>>>>>>>> commands (which may call ones that alter the model).  Unsure if it 
>>>>>>>> might 
>>>>>>>> actually happen but might have to take into account possible race 
>>>>>>>> conditions for if other messages appear before your other expected 
>>>>>>>> ones are 
>>>>>>>> processed through?  Easier to do that atomically all at once?
>>>>>>>>
>>>>>>>>
>>>>>>>> On Thursday, August 11, 2016 at 2:25:22 PM UTC-6, Kasey Speakman 
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> doSideEffects above would also have to map Cmd Evt to Cmd Msg.
>>>>>>>>>
>>>>>>>>

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to