Elm 0.18 中的动态记录
Dynamic records in Elm 0.18
我的 Elm 应用程序中的模型有一些嵌套记录。我目前正在使用普通的不可变函数设置它们。
Types.elm
type alias Model =
{ settings : Settings
...
}
type alias Settings =
{ username : String
, password : String
...
}
App.elm
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SetUsername username ->
( model |> setUserName username, Cmd.none )
SetPassword password ->
( model |> setPassword password, Cmd.none )
Setters.elm
setUserName : String -> Model -> Model
setUserName username model =
let
oldUserSettings =
model.userSettings
newUserSettings =
{ oldUserSettings | username = username }
in
{ model | userSettings = newUserSettings }
setPassword : String -> Model -> Model
setPassword password model =
let
oldUserSettings =
model.userSettings
newUserSettings =
{ oldUserSettings | password = password }
in
{ model | userSettings = newUserSettings }
我想概括设置器,以便我可以动态地设置它们。像这样:
setUserSettings : String -> String -> Model
setUserSettings field variable model =
let
oldUserSettings =
model.userSettings
newUserSettings =
{ oldUserSettings | field = variable }
in
{ model | userSettings = newUserSettings }
setUserName : String -> Model -> Model
setUserName value model =
setUserSettings username value
setPassword : String -> Model -> Model
setPassword value model =
setUserSettings password value
最像榆树的方法是什么?
如前所述,没有用于设置记录字段的内置语法。
由于这个限制,我认为您当前的代码没有问题。但是如果Settings
中出现更多的字段,将访问嵌套字段的逻辑提取到一个单独的函数中可能会有用:
setUserName : String -> Model -> Model
setUserName username model =
setUserSettings model (\r -> { r | username = username })
setPassword : String -> Model -> Model
setPassword password model =
setUserSettings model (\r -> { r | password = password })
setUserSettings : Model -> (Settings -> Settings) -> Model
setUserSettings model updateSettings =
let
oldUserSettings =
model.userSettings
newUserSettings =
updateSettings oldUserSettings
in
{ model | userSettings = newUserSettings }
如果出现更深的嵌套,您可能会发现 focus library useful. Here 是其用法的示例。
在您当前的情况下,库会将您的代码修改为:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
let
userSettings =
create .userSettings (\f r -> { r | userSettings = f r.userSettings })
username =
create .username (\f r -> { r | username = f r.username })
password =
create .password (\f r -> { r | password = f r.password })
in
case msg of
SetUsername value ->
( set (userSettings => username) value model, Cmd.none )
SetPassword value ->
( set (userSettings => password) value model, Cmd.none )
但这两种解决方案都不完美,因为您需要为每个字段定义自定义 setter。
我的 Elm 应用程序中的模型有一些嵌套记录。我目前正在使用普通的不可变函数设置它们。
Types.elm
type alias Model =
{ settings : Settings
...
}
type alias Settings =
{ username : String
, password : String
...
}
App.elm
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SetUsername username ->
( model |> setUserName username, Cmd.none )
SetPassword password ->
( model |> setPassword password, Cmd.none )
Setters.elm
setUserName : String -> Model -> Model
setUserName username model =
let
oldUserSettings =
model.userSettings
newUserSettings =
{ oldUserSettings | username = username }
in
{ model | userSettings = newUserSettings }
setPassword : String -> Model -> Model
setPassword password model =
let
oldUserSettings =
model.userSettings
newUserSettings =
{ oldUserSettings | password = password }
in
{ model | userSettings = newUserSettings }
我想概括设置器,以便我可以动态地设置它们。像这样:
setUserSettings : String -> String -> Model
setUserSettings field variable model =
let
oldUserSettings =
model.userSettings
newUserSettings =
{ oldUserSettings | field = variable }
in
{ model | userSettings = newUserSettings }
setUserName : String -> Model -> Model
setUserName value model =
setUserSettings username value
setPassword : String -> Model -> Model
setPassword value model =
setUserSettings password value
最像榆树的方法是什么?
如前所述,没有用于设置记录字段的内置语法。
由于这个限制,我认为您当前的代码没有问题。但是如果Settings
中出现更多的字段,将访问嵌套字段的逻辑提取到一个单独的函数中可能会有用:
setUserName : String -> Model -> Model
setUserName username model =
setUserSettings model (\r -> { r | username = username })
setPassword : String -> Model -> Model
setPassword password model =
setUserSettings model (\r -> { r | password = password })
setUserSettings : Model -> (Settings -> Settings) -> Model
setUserSettings model updateSettings =
let
oldUserSettings =
model.userSettings
newUserSettings =
updateSettings oldUserSettings
in
{ model | userSettings = newUserSettings }
如果出现更深的嵌套,您可能会发现 focus library useful. Here 是其用法的示例。
在您当前的情况下,库会将您的代码修改为:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
let
userSettings =
create .userSettings (\f r -> { r | userSettings = f r.userSettings })
username =
create .username (\f r -> { r | username = f r.username })
password =
create .password (\f r -> { r | password = f r.password })
in
case msg of
SetUsername value ->
( set (userSettings => username) value model, Cmd.none )
SetPassword value ->
( set (userSettings => password) value model, Cmd.none )
但这两种解决方案都不完美,因为您需要为每个字段定义自定义 setter。