My mistake, SubmitCustomerChanges was supposed to be UpdateCustomer above.
On Thursday, August 11, 2016 at 3:16:12 PM UTC-5, Kasey Speakman wrote:
>
> Oh! What I was doing in my examples was pretending there was a version of
> Elm that natively supported `command` and `update` methods instead of just
> `update`. I was exploring what that could look like, how it would affect
> things.
>
> I don't have a complete example in mind. The original post was more to get
> the idea out there and discuss it.
>
> So, I suppose I could also explore putting the command/event separation
> into practice as subsets of Msg which should work with non-imaginary Elm.
>
> type Act
> = UpdateCustomer customer
> | ... -- another command
>
> type Evt
> = NameChanged name
> | CustomerUpdateRequested
> | CustomerUpdateFailed err
> | CustomerUpdateSucceeded
>
> type Msg
> = Action act
> | Event evt
>
> doSideEffects: Act -> Model -> Cmd Evt
> doSideEffects act model =
> case act of
> SubmitCustomerChanges customer ->
> Cmd.batch
> [ Cmd.fromEvt CustomerUpdateRequested
> , callServerWithCustomer customer -- or model.Customer?
> ]
>
> ...
>
> updateModel: Evt -> Model -> Model
> ... -- implementation as previous
>
> update : Msg -> Model -> (Model, Cmd Msg)
> update msg model =
> case msg of
> Action act ->
> (model, doSideEffects act model)
>
> Event evt ->
> (updateModel evt model, Cmd.none)
>
> Apologize for errors... writing code in this groups editor.
>
> Anyway, this is the other choice I mentioned where you could let the view
> send either a command or event. This could prevent redundant "commands",
> example: `onInput`s which only change the model could issue an event
> directly instead of a command first. I thought this would require more
> discipline to use, but now that I see it, I think using "commands" (Action
> above) and "events" appropriately is enforced by `update`. If you want an
> event when an action happens, you could use a Cmd.batch (as in
> CustomerUpdateRequested above). That enforces model updates being separate
> messages from effects.
>
> For event-sourcing, you could replay only the `Event`s in complete
> isolation of the outside world to arrive at an interesting UI state. For
> example, an incorrect state that was bug reported.
>
> On Thursday, August 11, 2016 at 2:21:42 PM UTC-5, Kasey Speakman wrote:
>>
>> I'm not sure I like it either. Seems like a lot of UI commands would just
>> be auto-converted to events by `command`.
>>
>> However, in your example, I'm not sure what your filter code is about (my
>> ignorance). If I am understanding it right, it's filling in for the case
>> when you need to respond to an event and issue another command. This also
>> seems like a separate concern from what I mentioned.
>>
>> On Thursday, August 11, 2016 at 1:53:15 PM UTC-5, OvermindDL1 wrote:
>>>
>>> Yeah I was playing with the idea for more message types though still not
>>> convinced yet. Let's go hog-wild for a second to see how it would look
>>> with a fairly major overhaul and multiple message types though:
>>> ```elm
>>>
>>> {-| Msg is used for global message dispatching, handled only by the
>>> `filters` callback -}type Msg
>>> = ConnectTo Int
>>> | RoomConnected Int
>>> | ReceivedMessage String
>>> | MsgOnInput String
>>> | SendMsgDo
>>> type CmdMsg
>>> = FocusInputBox
>>> | ScrollInputBox
>>> | ConnectToRoom Int
>>> | SendMsgToRoom String
>>> type UpdMsg
>>> = JoinedRoom
>>> | MsgTyped String
>>> | MsgSent
>>> type alias Model =
>>> { uid : Int
>>> , msg : String
>>> , msgs : List String
>>> }
>>> init : ( Model, Cmd Msg )init = ( Model 0 "" [], connectToServer )
>>> filters : Msg -> Model -> States Model Msgfilters msg model =
>>> case msg of
>>> ConnectTo rid -> States.enableAll |> States.sendCommand (ConnectToRoom
>>> rid)
>>> RoomConnected uid ->
>>> States.enableAll
>>> |> States.sendCommand FocusInputBox
>>> |> States.sendCommand ScrollInputBox
>>> |> States.sendUpdate JoinedRoom
>>> ReceivedMessage msg -> States.enableAll
>>> MsgOnInput msg -> States.enableAll |> States.sendUpdate (MsgTyped msg)
>>> SendMsgDo -> States.enableAll |> States.sendCommand (SendMsgToRoom
>>> model.msg)
>>> update : UpdMsg -> Model -> Modelupdate msg model =
>>> case msg of
>>> JoinedRoom -> { model | msg="", msgs=[] }
>>> MsgTyped msg -> { model | msg=msg }
>>> MsgSent ->{ model | msg="" }
>>> command : Msg -> Model -> Cmd Msgcommand msg model =
>>> case msg of
>>> FocusInputBox -> focusMessageInput
>>> ScrollInputBox -> scrollScrollable Helpers Scrollable_Bottom
>>> ".messenger-mesglist"
>>> ConnectToRoom rid -> connectToRoom rid
>>> SendMsgToRoom msg -> sendMsgToConnectedRoom msg
>>>
>>> ```
>>>
>>> Eh I am not sure I like it, at all actually. It basically converts the
>>> usual helper functions into in-line in the case branches. It separates the
>>> commands and update messages out, however all the original logic is now in
>>> filter, which is basically just redistributing things (maybe it should be
>>> called `router` at this point) and is growing larger then its purpose was
>>> meant. Not sure of a good API yet...
>>>
>>>
>>> On Thursday, August 11, 2016 at 12:32:44 PM UTC-6, Kasey Speakman wrote:
>>>>
>>>> I do like the signatures you mentioned:
>>>>
>>>> `update : Msg -> Model -> Model`
>>>> `command: Msg -> Model -> Cmd Msg`
>>>>
>>>> However at that point, it no longer makes sense to use the same
>>>> messages for effects and model updates. For example:
>>>>
>>>> `update: Evt -> Model -> Model`
>>>> `command: Act -> Model -> Cmd Evt`
>>>>
>>>> Here, using Act for commands since Cmd is already taken. Evt for events
>>>> (facts which have occurred).
>>>>
>>>> The question then becomes how `view` would be affected. Html Msg
>>>> doesn't work there. If you did Html Act, then there is some boilerplate
>>>> for
>>>> actions that don't have effects:
>>>>
>>>> ```
>>>> -- FUTURE READER: THIS IS AN EXAMPLE, NOT ACTUAL SYNTAX
>>>> command : Act -> Model -> Cmd Evt
>>>> command act model =
>>>> case act of
>>>> ChangeName name ->
>>>> Cmd.fromEvt <| NameChanged name
>>>>
>>>> SubmitCustomerChanges customer ->
>>>> Cmd.batch
>>>> [ Cmd.fromEvt <| CustomerChangesSubmitted
>>>> , callServerWithCustomer customer -- or model.Customer?
>>>> ]
>>>> ```
>>>>
>>>> An alternative is to allow Html to produce either Act or Evt. But that
>>>> feels wrong. It would be too easy to try to use only one or the other for
>>>> all the work.
>>>>
>>>> On Thursday, August 11, 2016 at 1:03:47 PM UTC-5, Kasey Speakman wrote:
>>>>>
>>>>> It was just something that bugged me when I first saw it in the
>>>>> examples, and I just came to the realization of why. And I am wondering
>>>>> out
>>>>> loud what it look like if they were separate things.
>>>>>
>>>>> In your example case, you could make a 3rd command that did the issued
>>>>> a new message InfoConnectIdAssigned to separate the model bit out. The
>>>>> tradeoff is isolation of model changes vs increased boilerplate (issuing
>>>>> a
>>>>> no-effect command). I think a shortcut method could be in order like
>>>>> Cmd.none, but something like Cmd.fromMsg.
>>>>>
>>>>> On Thursday, August 11, 2016 at 12:53:16 PM UTC-5, OvermindDL1 wrote:
>>>>>>
>>>>>> I guess what you are proposing is separating a Message into a
>>>>>> 'commands' and 'update' callbacks? That could work well too... I could
>>>>>> add that as an option to my ProgramEx testing library (where I test with
>>>>>> extra callbacks) if you want to play around with it? Do you propose
>>>>>> that
>>>>>> `update` would be `Msg -> Model -> Model` and `command` would be `Msg ->
>>>>>> Model -> Cmd Msg, running in sequence of command before update? I can
>>>>>> see
>>>>>> a lot of them having a lot of duplicate code though, but I guess that
>>>>>> could
>>>>>> be removed from my currently testing `filters` callback to clean up the
>>>>>> message into more pure stateful messages. Though if I did that I really
>>>>>> think I would want to make two different message types, one for filters
>>>>>> and
>>>>>> one for consuming, however that may make larger API changes than would
>>>>>> be
>>>>>> easy... What precisely would you want it to look like?
>>>>>>
>>>>>>
>>>>>> On Thursday, August 11, 2016 at 11:48:21 AM UTC-6, OvermindDL1 wrote:
>>>>>>>
>>>>>>> Just as an aside, but I quite often return a mutated model *and*
>>>>>>> commands, such as this for the shortest example I am finding:
>>>>>>> ```elm
>>>>>>>
>>>>>>> InfoConnect uid ->
>>>>>>> ( { model | uid = uid }
>>>>>>> , Cmd.batch
>>>>>>> [ connect_roomlist 0
>>>>>>> , connect_roomlist uid
>>>>>>> ]
>>>>>>> )
>>>>>>>
>>>>>>> ```
>>>>>>> So when we connected to the server, got an InfoConnect message back
>>>>>>> with the unique ID of the user, they then are allowed to connect to
>>>>>>> both
>>>>>>> the public and their personal room lists, so I submit those connection
>>>>>>> requests.
>>>>>>>
>>>>>>>
>>>>>>> On Thursday, August 11, 2016 at 11:37:48 AM UTC-6, Kasey Speakman
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> Hi all,
>>>>>>>>
>>>>>>>> I'm getting to know Elm. I recently read this article
>>>>>>>> <http://marcosh.github.io/post/2016/07/09/elm-event-sourcing.html>
>>>>>>>> about event sourcing in Elm. Essentially, the time-traveling debugger
>>>>>>>> is
>>>>>>>> event sourcing. But it's a pattern that could be used in an app for
>>>>>>>> other
>>>>>>>> great things. (Lots of literature on that in the internet. One
>>>>>>>> particular
>>>>>>>> interest of mine is producing a complete failing use case from live
>>>>>>>> running
>>>>>>>> app -- it's just all the events. Obviously wouldn't work for real-time
>>>>>>>> apps... too many events... but for most of mine it would.)
>>>>>>>>
>>>>>>>> However, one thing that is a hindrance (to the TTD as well) and
>>>>>>>> that has always bothered me about the Elm examples is this signature.
>>>>>>>>
>>>>>>>> update : Msg -> Model -> (Model, Cmd Msg)
>>>>>>>>
>>>>>>>>
>>>>>>>> Because an update returns both a Model and Cmd, for instance, the
>>>>>>>> time-traveling debugger "...needs to tell the runtime not to perform
>>>>>>>> any
>>>>>>>> side-effects during replay to avoid these issues"[1]. An
>>>>>>>> event-sourcing
>>>>>>>> implementation would have to figure a way to do the same without
>>>>>>>> runtime
>>>>>>>> hooks.
>>>>>>>>
>>>>>>>> This part of the architecture mixes concerns by returning a model
>>>>>>>> and effects. And usually (not always) you see each message returning
>>>>>>>> one or
>>>>>>>> the other, not both. From the docs:
>>>>>>>>
>>>>>>>> update : Msg -> Model -> (Model, Cmd Msg)
>>>>>>>> update msg model =
>>>>>>>> case msg of
>>>>>>>> Roll ->
>>>>>>>> (model, Random.generate NewFace (Random.int 1 6))
>>>>>>>>
>>>>>>>> NewFace newFace ->
>>>>>>>> (Model newFace, Cmd.none)
>>>>>>>>
>>>>>>>>
>>>>>>>> Here, Roll does an effect, but nothing with the model. NewFace
>>>>>>>> returns a new model but no effects. You do have cases where you want
>>>>>>>> to
>>>>>>>> update a UI element when an outside effect happens, like activating a
>>>>>>>> spinner when sending off an HTTP request. Those could still be modeled
>>>>>>>> as
>>>>>>>> two "Cmd"s. One that immediately returns a separate message affecting
>>>>>>>> the
>>>>>>>> model's spinner. And another to do the HTTP request.
>>>>>>>>
>>>>>>>> So it seems to me that there are really two concepts at work here.
>>>>>>>> There are "events" which have happened and can be used completely
>>>>>>>> deterministically, and there are commands which interface with the
>>>>>>>> outside
>>>>>>>> and may produce events.
>>>>>>>>
>>>>>>>> I think it's something worth pointing out and considering for the
>>>>>>>> future. What do y'all think?
>>>>>>>>
>>>>>>>> Kasey
>>>>>>>>
>>>>>>>> [1] source <http://debug.elm-lang.org/>, section "How Elm makes
>>>>>>>> this possible", subsection "Purity", last paragraph
>>>>>>>>
>>>>>>>
>
> On Thursday, August 11, 2016 at 2:26:24 PM UTC-5, OvermindDL1 wrote:
>>
>> Can you supply a complete example of what you want it to look like
>> (excepting view, we don't care about view right now).?
>>
>>
>> On Thursday, August 11, 2016 at 1:25:38 PM UTC-6, OvermindDL1 wrote:
>>>
>>> In this case it is just filling in for 'something' that can dispatch
>>> some messages to `update` and dispatch commands to `command`. I'm not sure
>>> how to dispatch those without some dispatcher that is already acting like
>>> the existing update...
>>>
>>>
>>> On Thursday, August 11, 2016 at 1:21:42 PM UTC-6, Kasey Speakman wrote:
>>>>
>>>> I'm not sure I like it either. Seems like a lot of UI commands would
>>>> just be auto-converted to events by `command`.
>>>>
>>>> However, in your example, I'm not sure what your filter code is about
>>>> (my ignorance). If I am understanding it right, it's filling in for the
>>>> case when you need to respond to an event and issue another command. This
>>>> also seems like a separate concern from what I mentioned.
>>>>
>>>> On Thursday, August 11, 2016 at 1:53:15 PM UTC-5, OvermindDL1 wrote:
>>>>>
>>>>> Yeah I was playing with the idea for more message types though still
>>>>> not convinced yet. Let's go hog-wild for a second to see how it would
>>>>> look
>>>>> with a fairly major overhaul and multiple message types though:
>>>>> ```elm
>>>>>
>>>>> {-| Msg is used for global message dispatching, handled only by the
>>>>> `filters` callback -}type <span style="color:rg
>>>>>
>>>>>
--
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.