This is super cool.
But what is the function:

(!) : a -> List b -> (a, b)

On Wednesday, 1 June 2016 09:45:05 UTC+2, James Wilson wrote:

Thanks for your help; I'll have a ponder and probably end up taking an 
> effect manager route again (I started this way and then ended up with some 
> weird hybrid where my cache was in the main elm app and an effect manager 
> did the "lower level" api stuff; but I'm not so happy with it)
>
> As another effect manager code point if you're intrigued how they work 
> (and my comments are in any way useful, which they may not be); here's an 
> effect manager I made for sending and receiving things from a backend I'm 
> wiring my app up to (so it uses custom Cmds and Subs):
>
>
> https://github.com/jsdw/tl-asset-browser/blob/3e9e8527f65ae0a0a2d5d00d01779bdfdf03701d/src/elm/Api.elm
>
> Not sure whether it's any help (may just be easier looking at the elm-lang 
> effect managers!) but just in case :)
>
> On Wednesday, 1 June 2016 08:31:11 UTC+1, Peter Damoc wrote:
>>
>> I haven't used an effect manager for this because I haven put in the time 
>> needed to learn how to create effect managers. :) 
>>
>> If what I've shown here can be accomplished with an effect manager then 
>> that's the way it should be done.  :) 
>>
>>
>>
>>
>>
>>
>> On Wed, Jun 1, 2016 at 10:21 AM, James Wilson <[email protected]> wrote:
>>
>>> Thanks, that looks like basically exactly what I'd have guessed :) It's 
>>> super useful seeing an actual code sample with these ideas in.
>>>
>>> One thing I wonder now is; why not use an effect manager for this? It 
>>> basically seems to fit the exact same space (allows you to create a custom 
>>> Req like thing that can be mapped and batched and passed up the component 
>>> hierarchy - except that it's just a Cmd instead and plays nice with other 
>>> Cmds; allows you to maintain and update state (the cache) as you go; allows 
>>> you to "convert" Reqs to tasks to be run - just Cmds again now). In fact, 
>>> effect managers don't really seem to help you do anything other than what's 
>>> described here (plus a subscription side if you want it). Are there any 
>>> cons to using an effect manager here that you have in mind?
>>>
>>> On Tuesday, 31 May 2016 20:43:41 UTC+1, Peter Damoc wrote:
>>>>
>>>> The updating of the cache sounds to me like this: 
>>>>
>>>> 1. if we have the info in cache, just supply the info without a HTTP GET
>>>> 2. if we don't have the info in cache, return a different Msg that 
>>>> encapsulates the msg that requested the original information and the info 
>>>> required for the cache update. 
>>>>
>>>> Here is a quick update of the code I've previously posted to include 
>>>> this caching mechanism. 
>>>>
>>>> https://gist.github.com/pdamoc/d492ab58023926cd4d4950f12e5e170d
>>>>
>>>>
>>>>
>>>>
>>>> On Tue, May 31, 2016 at 10:05 PM, James Wilson <[email protected]> 
>>>> wrote:
>>>>
>>>>> The key part that's not coded in the gist is the use of a cache/global 
>>>>> state object, however I think I  see what you're getting at - pass back 
>>>>> up 
>>>>> the chain a Req object, say, and at the top we can turn it into a Cmd 
>>>>> using, say, some top level global state as well as whatever other data we 
>>>>> need. This may lead to a request being made to the server or it may not.
>>>>>
>>>>> The other part of the puzzle is actually updating the cache when a 
>>>>> request is made. Req.toCmd for instance could return an updated 
>>>>> GlobalState 
>>>>> so that it's able to cache "pending" states on values (so that we can 
>>>>> avoid 
>>>>> duplicating requests). To update the cache when the response actually 
>>>>> comes 
>>>>> in we could have toCmd return a Cmd.batch of 2 commands, one that will 
>>>>> fail/succeed and send a message to the component that initiated the Req, 
>>>>> and one that will send a message aimed at the top level cache itself.
>>>>>
>>>>> Thanks Peter, I'll definitely mull over this!
>>>>>
>>>>> On Tuesday, 31 May 2016 19:45:42 UTC+1, Peter Damoc wrote:
>>>>>>
>>>>>> ADT in Elm is one of its most powerful weapons. 
>>>>>>
>>>>>> You could encapsulate your requests in a type and use this type at 
>>>>>> top level to fulfill them. 
>>>>>>
>>>>>> For example: instead of returning Cmd msg you return some Req msg 
>>>>>> that can be turned into a Cmd msg at top level based on some context 
>>>>>> information. 
>>>>>>
>>>>>> Here is a gist with a skeleton of how I view this implemented:
>>>>>> https://gist.github.com/pdamoc/a47090e69b75433efa60fe4f70e6a06a
>>>>>>
>>>>>> I've sent the base of the URL as a simple String in `Req.toCmd` but 
>>>>>> you can imagine a more complex type holding all kind of information 
>>>>>> (e.g. 
>>>>>> cache, auth, etc ) . 
>>>>>> Also, I've kept the type of the Req simple (only saved the rest of 
>>>>>> the URL based on the user and the request) but one could use it to store 
>>>>>> all the info needed when you will turn the Req into a Cmd. 
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2016 at 7:29 PM, James Wilson <[email protected]> 
>>>>>> wrote:
>>>>>>
>>>>>>> In Elm, each component basically has its own internal state (which 
>>>>>>> is actually all just a slice of one global model). In my app, I also 
>>>>>>> want 
>>>>>>> global state that is independant of any components; for example a 
>>>>>>> clientside cache of various API responses (asset details - there could 
>>>>>>> be 
>>>>>>> many thousands, user authentication status).
>>>>>>>
>>>>>>> I want any component to be able to call methods that make use of 
>>>>>>> this global state. For example, a method to obtain details for items in 
>>>>>>> the 
>>>>>>> current view might first look at the global state to see if these items 
>>>>>>> are 
>>>>>>> cached. If they arent, the call would provide a Cmd to be issued that 
>>>>>>> gets 
>>>>>>> the items (and puts them in the cache), while simultaneously updating 
>>>>>>> the 
>>>>>>> state to indicate that they are being loaded (so that the same request 
>>>>>>> again from another component doesnt trigger another call to the 
>>>>>>> backend). 
>>>>>>> If they are cached, they can be easily returned from there. A first 
>>>>>>> shot at 
>>>>>>> a signature might look something like:
>>>>>>>
>>>>>>> getItem : GlobalState -> ID -> Tag -> (GlobalState, Cmd msg)
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> However we could partially apply functions that exist on some 
>>>>>>> globalState instantiation to hdie the initial state being passed in and 
>>>>>>> end 
>>>>>>> up with:
>>>>>>>
>>>>>>> state.items.getItem : ID -> Tag -> (GlobalState, Cmd msg)
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> The downside of this approach is that I have to thread this state 
>>>>>>> through multiple calls that might make use of it, and thread it back up 
>>>>>>> explicitly through the update functions to get it back to the top. At 
>>>>>>> the 
>>>>>>> top we'd then have something like (excuse any mistakes!):
>>>>>>>
>>>>>>> update msg model = case msg of
>>>>>>>    SubMsg m ->
>>>>>>>      let (newSubModel, subCmds, newGlobalState) = SubComponent.update 
>>>>>>> m model.subModel
>>>>>>>      in ({ model | state = newGlobalState, subModel = newSubModel}, 
>>>>>>> Sub.map SubMsg subCmds)
>>>>>>>    ...
>>>>>>>
>>>>>>>
>>>>>>> An alternative approach is to hold this global state in an effect 
>>>>>>> manager, and so in the app you'd end up using the Cmd/Sub mechanism to 
>>>>>>> ask 
>>>>>>> for things from the state and internally initiate API requests to 
>>>>>>> update 
>>>>>>> the state as necessary. We'd end up with an API more like:
>>>>>>>
>>>>>>> getItem : ID -> Tag -> Cmd msg
>>>>>>>
>>>>>>>
>>>>>>> or
>>>>>>>
>>>>>>> state.items.getItem : ID -> Tag -> Cmd msg
>>>>>>>
>>>>>>>
>>>>>>> where the returned Cmd would either lead to an item being sent to 
>>>>>>> the component immediately via a cache (where Tag is a Msg type the 
>>>>>>> component knows about) or after it was obtained via some backend. This 
>>>>>>> would make all retrieving of state async but seems to simplify the 
>>>>>>> interface (perhaps at the cost of more complexity in implementing the 
>>>>>>> effect manager).
>>>>>>>
>>>>>>> Which approach do people think is best for working with global state 
>>>>>>> (neither is an option if you have a better way!)? Do you get away with 
>>>>>>> not 
>>>>>>> needing this kind of thing (and if so, how)? I'd love to hear back, 
>>>>>>> especially from those that have had experience building larger apps in 
>>>>>>> Elm!
>>>>>>>
>>>>>>> -- 
>>>>>>> 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.
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> -- 
>>>>>> There is NO FATE, we are the creators.
>>>>>> blog: http://damoc.ro/
>>>>>>
>>>>> -- 
>>>>> 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.
>>>>>
>>>>
>>>>
>>>>
>>>> -- 
>>>> There is NO FATE, we are the creators.
>>>> blog: http://damoc.ro/
>>>>
>>> -- 
>>> 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.
>>>
>>
>>
>>
>> -- 
>> There is NO FATE, we are the creators.
>> blog: http://damoc.ro/
>>
> ​

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