I'm guessing you referring to: http://package.elm-lang.org/packages/elm-lang/core/4.0.1/Platform-Cmd#!
This is the code : (!) : model -> List (Cmd msg) -> (model, Cmd msg) (!) model commands = (model, batch commands) I use it as a short hand for joining the model and the Cmds. It's also pretty handy when you don't have a Cmd since `batch []` evaluates to Cmd.none. On Wed, Jun 1, 2016 at 10:18 PM, Simon <[email protected]> wrote: > 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. > -- 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.
