如何在Elm中的模型中添加嵌套元素

时间:2016-12-05 06:05:13

标签: record elm

是否有标准方法可以执行以下操作?

{ model | country =
  { model.country | state =
    { model.country.state | city =
      { model.country.state.city | people =
        model.country.state.city.people ++ [ newPerson ]
      }
    }
  }
}

当然,countrystatecity是嵌套在model中的记录。我只是想在嵌套的city记录中添加一个人。

以上实际上并不奏效。我在第一次提到model.country时收到以下错误:

  

我正在寻找以下其中一项:

"'"
"|"
an equals sign '='
more letters in this name
whitespace

我能够让它工作的方法就是在每一步都调用一个函数:

{ model | country = updateCountry newPerson model.country }

updateCountry person country =
  { country | state = updateState newPerson country.state }

然后updateStateupdateCity ...

相同

2 个答案:

答案 0 :(得分:2)

截至今天(prefix_:envtablename),记录更新语法中不允许使用任意表达式。

换句话说,您无法在更新期间访问记录的字段:

0.18.0

对于Elm编译器来说,它是planned feature,但就目前而言,您应该考虑重构模型或使用其中一个冗长的解决方法。

就个人而言,我更喜欢model = { model.topProperty | childProperty = "Hello" } ^^^^^^^^^^^^^^^^^ Syntax error 表达式,但我从不使用深度大于3的记录。

let..in示例

它看起来非常冗长,但这种方法并没有什么不好。当Elm Compiler支持更好的语法时,你将会重构它。

将此作为开发一组辅助函数的起点,用于不同级别的更新。

let..in

答案 1 :(得分:1)

如果你想做这样的事情,通常最好让记录结构更平坦 典型地:

    如果您的操作也是嵌套的,则
  • 嵌套记录是正常的:如果您对每个级别都有单独的更新功能。和/或如果您只想在自己的级别更新嵌套记录。
  • 如果您需要对某些嵌套记录进行根级别访问,那么flat更好。

我倾向于将所有内容存储在根级别,并包含ID以供参考。对于你的例子,这看起来像这样:

type alias Model =
  { persons : Dict PersonID Person
  , cities : Dict CityID City
  , states : Dict StateID State
  , countries : Dict CountryID Country
  }

此结构允许您从根级别到所有实体的完全访问权限。 所以添加一个人就是:

  { model 
  | persons =
      model.persons
      |> Dict.insert newPersonID newPerson
  }

要获得一个国家的所有城市,现在可以做更多的工作BTW:

citiesInCountry : Model -> CountryID -> Dict CityID City
citiesInCountry model countryID = 
    let
      statesInCountry =
        model.states
        |> Dict.filter (\id state -> state.countryID == countryID)
    in
      model.cities
      |> Dict.filter (\id city -> Dict.member city.stateID statesInCountry)

所以这取决于您的应用中哪种操作更频繁:

  • 如果你有很多像&#34这样的操作;得到所有的孙子",那么嵌套的方法可能会更好
  • 如果你有很多"更新这个孙子",那么平面替代品可能更适合