Сгиб и карта одновременно - PullRequest
2 голосов
/ 21 апреля 2020

У меня есть функция

f : a -> b -> ( a, c )

, и мне нужно применить f к списку b, в то время как a накапливается и c добавляется в список, получая ( a, List c ). Я думаю, что подпись того, что я хочу сделать, это

( a -> b -> ( a, c ) ) -> a -> List b -> ( a, List c )

Реальный сценарий здесь заключается в том, что у меня есть

getThing : Model -> Thing -> ( Model, Cmd Msg )

и мне нужно запустить getThing в списке Thing, передавая Model каждому вызову getThing и возвращая модель и все Cmd s, которые должны быть выполнены в Platform.Cmd.batch.

Я думаю, что эта проблема должна быть разбить на несколько частей, но я не уверен, с чего начать. Такое ощущение, что использование * сгиба подходит для Model, но мне нужна карта для Cmd части.

1 Ответ

5 голосов
/ 21 апреля 2020

Вам просто нужно распаковать кортеж, возвращаемый getThing в каждой итерации сгиба, а затем упаковать его обратно с командой, добавленной в накопленный список команд в качестве аккумулятора.

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

Именование здесь очень специфично c, чтобы помочь мнемонике, но его можно легко обобщить, просто используя более обобщенные c имена переменных.

...