在Elm中使用Dict.update和嵌套更新函数

时间:2016-12-05 19:24:06

标签: function dictionary elm

我正在编写一个Elm应用程序,其中该州的主要部分位于Dict,其中Record为值。我有一个主状态模型的更新函数,以及Dict中各个记录的更新函数。有没有办法将Dict.update与记录状态更新功能一起使用?

我遇到的问题是记录的状态更新函数返回更新函数通常返回的内容:具有更新对象的元组和要触发的任何命令(例如(newRecord, Cmd.none))。但是Dict.update函数需要记录并返回一条记录(例如只是newRecord),而不是带有记录和命令对象的元组。

有解决方法吗?现在我已经使用Dict.getDict.insert的组合工作了,但这看起来很笨拙。

3 个答案:

答案 0 :(得分:2)

如果记录的更新功能始终返回Cmd.none,则可以简化它并仅返回更新的模型。

如果您的应用程序架构不需要,那么子模块不必遵循( Model, Cmd Msg )约定。

如果您确实需要从较低级别传递命令,则还可以重新构建子模块的update函数以简化这些更新。

基于example/http

的示例

以下是一个如何拆分更新的示例,以便您可以在顶级update中重复使用相同的逻辑,而无需额外的诡计。

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  (updateModel msg model, updateCmd msg model)


updateCmd: Msg -> Model -> Cmd Msg
updateCmd msg model =
  case msg of
    MorePlease ->
      getRandomGif model.topic

    _ ->
      Cmd.none


updateModel: Msg -> Model -> Model
updateModel msg model =
  case msg of
    NewGif (Ok newUrl) ->
      Model model.topic newUrl

    _ ->
      model

如果您需要updateCmd中的更新模型,那么只需传递它而不是当前模型,或者如果您愿意,也可以传递它们。

作为奖励,您可以完全省略案例表达的未使用分支。

使用Dict.update

也可以在updateModel中使用Dict.update而无需检索记录并将其写回。

Dict.update childKey (Maybe.map (updateModel childMsg)) model

答案 1 :(得分:1)

不是我知道的。我在我的一个项目中有这个辅助函数

updateDict : comparable -> msg -> Dict comparable b -> (msg -> b -> ( b, Cmd msg )) -> (comparable -> msg -> c) -> ( Dict comparable b, Cmd c )
updateDict uid act dict fn wrapper =
    case Dict.get uid dict |> Maybe.map (fn act) of
        Just ( m, e ) ->
            ( Dict.insert uid m dict
            , Cmd.map (wrapper uid) e
            )

        Nothing ->
            ( dict, Cmd.none )

答案 2 :(得分:1)

不确定这是否是您要找的,但如果您的模型中有嵌套的Dict结构,请执行以下操作:

type alias Model =
  { parentsAndChildren : Dict String (Dict String Int) }

然后没有必要让孩子update输出Cmd。您的更新可能如下所示:

update : Msg -> Model -> Model
update msg model = 
  case msg of
    NewChild parentName childName age ->
      let
        newModel =
          { model
          | parentsAndChildren =
              model.parentsAndChildren
              |> Dict.update 
                   parentName 
                   (Maybe.map insertChild)
          }

      in
        (newModel, Cmd.none)

-- helper function to update a child Dict
insertChild: String -> Int -> Dict (String Int) -> Dict (String Int)
insertChild name age childDict =
  Dict.insert name age childDict

NEEDS 输出update的唯一Cmd功能是顶级组件中的更新功能。 因此,您的孩子update功能无需输出Cmd