>
> I now need knowledge of the sequencer to flow through the program in a way
> that effects managers avoid.
>

I disagree with this statement. I was hoping that by iterating through this
solution, we would eventually come to an agreement re: the claim quoted
above. But you are annoyed at me for treating your problem seriously, and
you are annoyed at Richard for dismissing your problem, so I don't really
know where to go from here.

On Fri, Aug 26, 2016 at 11:14 AM, Mark Hamburg <[email protected]>
wrote:

> As I said, I know how to write the queue if that's what I really want.
>
> My problem is that when a module uses the WebSocket.send function to
> create a command, I don't have to do anything special in my program to
> arrange for that command to make its way to the web socket effects manager.
> I just need to route it to my top level update function up through however
> many layers of the Elm architecture my app uses. When I want to use my HTTP
> fetch sequencer (again a contrived example that I had hoped would be simple
> enough not to get buried in discussions of how to build the sequencer), I
> now need knowledge of the sequencer to flow through the program in a way
> that effects managers avoid. I'm looking for a pattern that allows me to
> construct service APIs using the same sort of conventions used by effects
> managers and with the same sort of ability to not muck up the code with,
> for example, needing to change lots of uses of Cmd.map tagger to
> something more like Cmd.map (Wrapped.map tagger).
>
> Mark
>
> On Thu, Aug 25, 2016 at 10:37 PM, Nick H <[email protected]>
> wrote:
>
>> OK, here I am going for the obvious implementation again. Sorry the
>> formatting is a little nutty.
>>
>> type Action
>>     = HTTPResponse String
>> | SomethingElse
>>
>> type alias Model =
>>   { pendingFetches : List (Cmd msg)
>>   , waitingForResponse : Bool
>>   }
>>
>>
>> doAThing : Model -> List (Cmd Action)
>>
>>
>> update : Action -> Model -> (Model, Cmd Action)
>> update action model =
>>   case action of
>>     SomethingElse ->
>>  case (model.waitingForResponse, doAThing model) of
>>  (True, newFetches) ->
>>    ( { model | pendingFetches = model.pendingFetches ++ newFetches }
>> , Cmd.none )
>>      (False, head :: tail) ->
>>    ( { model
>>    | pendingFetches = model.pendingFetches ++ tail
>>    , waitingForResponse = True
>> }
>> , head )
>>  (False, []) ->
>>    ( model, Cmd.none )
>>
>>     HTTPResponse value ->
>>       let
>>         newModel = processResponse value model
>>       in
>>         case newModel.pendingFetches of
>>           head :: tail ->
>>             ( { newModel | pendingFetches = tail }, head )
>>
>>           [] ->
>>             ( { newModel | waitingForResponse = False }, Cmd.none )
>>
>> On Thu, Aug 25, 2016 at 9:39 PM, Mark Hamburg <[email protected]>
>> wrote:
>>
>>> Yes, a command queue is the obvious implementation for what I identified
>>> as a contrived example. The core problem, however, is how items get into
>>> the command queue through the normal command routing mechanisms.
>>>
>>> Mark
>>>
>>> On Aug 25, 2016, at 8:18 PM, Nick H <[email protected]> wrote:
>>>
>>> We might generate any number of these commands during a single update call,
>>>> but the mechanics of their execution demand that we not start the HTTP
>>>> fetch for one until the HTTP fetch for the previous has finished.
>>>
>>>
>>> One solution that comes to mind is adding a command queue to your model.
>>> Something along these lines:
>>>
>>> type alias Model =
>>>   { pendingFetches : List (Cmd msg) }
>>>
>>> update action model =
>>>   case action of
>>>     HTTPResponse value ->
>>>       let
>>>         newModel = processResponse value model
>>>       in
>>>         case newModel.pendingFetches of
>>>           head :: tail ->
>>>             ( { newModel | pendingFetches = tail }, head )
>>>
>>>           [] ->
>>>             ( newModel, Cmd.none )
>>>
>>> On Thu, Aug 25, 2016 at 5:51 PM, Mark Hamburg <[email protected]>
>>> wrote:
>>>
>>>> I'm going to try to take the large app design questions and focus them
>>>> on a more narrow and admittedly contrived example.
>>>>
>>>> Say the people doing the client coding needed to be able to take a URL
>>>> string and fetch a string via HTTP. (Yes, this is covered in the HTTL
>>>> module. Bear with me. I'm trying to keep the example simple.) Dealing with
>>>> tasks all over the place muddies up the client architecture that would
>>>> otherwise focus on commands for external operations. So, we define:
>>>>
>>>> getStringCommand :
>>>>     (Http.Error -> msg)
>>>>     -> (String -> msg)
>>>>     -> String
>>>>     -> Cmd msg
>>>>
>>>>
>>>> This is easy to write given the standard libraries.
>>>>
>>>> But now it turns out we would like to execute these one at a time. We
>>>> might generate any number of these commands during a single update
>>>> call, but the mechanics of their execution demand that we not start the
>>>> HTTP fetch for one until the HTTP fetch for the previous has finished. (I
>>>> said it was contrived. Maybe we want to automatically fail subsequent
>>>> commands if the first one fails.)
>>>>
>>>> From what I understand of effect managers, we could write an effect
>>>> manager to do this but the documentation around effect managers discourages
>>>> reaching for them as a solution. They are identified as being for library
>>>> writers and though this serialized string-fetcher seems a bit like a
>>>> library in its usage, it also feels like a chunk of general app
>>>> functionality. Or maybe the backend needs to use web sockets instead of
>>>> HTTP and we would like to use the web sockets effects manager as part of
>>>> the implementation.
>>>>
>>>> One way to address this is to replace commands with requests, recognize
>>>> string fetch requests when we reach a certain point in the model hierarchy,
>>>> and process them accordingly generating commands as we move up the rest of
>>>> the hierarchy. This has been covered in previous posts to the discussion
>>>> list. The downside to this is that it doesn't interoperate well with code
>>>> that wants to speak in terms of commands. One nice thing about effects
>>>> managers is that the addressing of a command to a particular effect manager
>>>> is essentially unseen by everything that handles it until we get to the app
>>>> runner. Having lots of code need to switch from returning commands to
>>>> returning requests is a very visible consequence of using this service that
>>>> speaks via requests.
>>>>
>>>> Another way to handle this is by changing update functions so that they
>>>> still speak commands, but they now have a signature like:
>>>>
>>>> update : Msg -> Model -> (Model, Cmd (Wrapped Msg))
>>>>
>>>>
>>>> We can then watch for wrapped commands and somehow unwrap the ones that
>>>> really are looking for work by the sequencer code. That said, I'm waving my
>>>> hands somewhat fast here and while we now continue to use commands, we
>>>> don't use them in the way we're used to so I don't know that it's a big win
>>>> over the requests approach.
>>>>
>>>> Is there a better way to do this that I'm not seeing? The example is
>>>> contrived but so are most examples. It feels like it gets at the sort of
>>>> problem for which there ought to be a design pattern — i.e., structure your
>>>> types and functions like this to solve this sort of problem.
>>>>
>>>> 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 [email protected].
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>> --
>>> 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.
>>>
>>> --
>>> 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.
>>>
>>
>> --
>> 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.
>>
>
> --
> 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.
>

-- 
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