So it seems that you would have something like a `commands` callback send
out commands, one of those would be a command just for sending messages to
`update` without sending the original message? (Also, it is already easy
to make commands from messages although Cmd.fromMsg would be shorter). So
you are thinking of something like:
```elm
commands : Msg -> Model -> Cmd Msgcommands msg model =
case msg of
Something blah -> Cmd.batch
[ doSomething
, Cmd.fromMsg MyUpdateMsg blah
]
update : ChangeMsg -> Model -> Modelupdate msg model =
case msg of
MyUpdateMsg blah = { model | blah = blah }
```
I am unsure about making model changes be a command like that to be honest.
I'd probably opt for something more like:
```elm
commands : Msg -> Model -> Cmd Msgcommands msg model =
case msg of
Something blah -> Cmd.batch
[ doSomething
]
update : Msg -> Model -> Modelupdate msg model =
case msg of
Something blah = { model | blah = blah }
```
Where the commands happen first then the model update, however you will
often have to do the same calculations in both to figure out something when
a message causes both (as some of mine do), which is duplicating effort.
Something that might work that I could see would be something like with the
filters callback I propose:
```elm
filters : BaseMsg -> Model -> ( Msg, States Model Msg )filters msg model =
case msg of
ReceivedAMsg blah ->
( Something (blah+42), States.enableAll )
commands : Msg -> Model -> Cmd Msgcommands msg model =
case msg of
Something blah -> Cmd.batch
[ doSomething
]
update : Msg -> Model -> Modelupdate msg model =
case msg of
Something blah = { model | blah = blah }
```
But even that does the returning two things that you mention but in
filters, although I think they are inextricably tied together so they make
sense, maybe change `filters` to a different API like:
```elm
filters : BaseMsg -> Model -> States Model Msgfilters msg model =
case msg of
ReceivedAMsg blah -> States.enableAll |> States.sendMsg (Something
(blah+42))
```
Although then you have to pass forward every single message manually, which
might not be a bad things all considered, but definitely more wordy and not
really any more clear. Maybe make `BaseMsg` just be `Msg` again and have
States control whether the original message is overridden or not, that
seems more clear to me, if no override is specified for the message then it
just passes through the original. I still do not think I like that though.
Cannot think that commands could be a one-off subscription either.
Eh, I am not really sure, decoupling Commands from the Updates is going to
cause a lot of code duplication, which you could resolve via a filters
function but then you get a lot more Message types, which although would
make things clear, not sure of how it should follow out to the end there
yet... Maybe if filters had a way to send out more messages than just one,
or different types of messages...
On Thursday, August 11, 2016 at 12:03:47 PM UTC-6, 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
>>>>
>>>
--
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.