Reputation: 23
I have a function
f : a -> b -> ( a, c )
and I need to apply f
to a list of b
, while a
is accumulated and c
is appended to a list, getting ( a, List c )
. I think the signature of what I want to do is
(a -> b -> ( a, c )) -> a -> List b -> ( a, List c )
The real scenario here is that I have
getThing : Model -> Thing -> ( Model, Cmd Msg )
and need to run getThing
on a list of Thing
, passing the Model
to each call to getThing
and returning the model and all Cmd
s that are to be performed in a Platform.Cmd.batch
.
I think this problem should be broken down into multiple parts, but I am not sure where to start. It feels like using a fold is appropriate for the Model
, but I need a map for the Cmd
part.
Upvotes: 2
Views: 429
Reputation: 73
If you don't mind pulling in another package, there's elm-community/list-extra List.Extra.mapAccuml and List.Extra.mapAccumr
https://package.elm-lang.org/packages/elm-community/list-extra/latest/List-Extra#mapAccuml
Upvotes: 1
Reputation: 29106
You just need to unpack the tuple returned by getThing
in each iteration of the fold, then pack it back up with the command added to the accumulated list of commands as the accumulator.
mapThings : (a -> b -> ( a, c )) -> a -> List b -> ( a, List c )
mapThings getThing initialModel things =
List.foldl
(\thing ( model, cmds ) ->
let
( newModel, cmd ) =
getThing model thing
in
( newModel, cmd :: cmds )
)
( initialModel, [] )
things
The naming here is very specific to help mnemonics, but it can easily be generalized just by using more generic variable names.
Upvotes: 5