如何编写更新记录字段的通用函数
How to write a generic function that updates fields of a Record
考虑
type alias Rec = { a: Int, b: Int, c:Int }
updateRec r aVal = { r|a = aVal }
updateRec2 r aVal bVal = { r|a = aVal, b= bVal }
updateRec3 r aVal bVal cVal = ...
如何将 updateRec
和 updateRec2
... 概括为一个函数?
您想编写一个具有可变数量的不同类型参数的函数。这在动态类型语言(Javascript、Python、Ruby)中很常见,但在类型语言中通常是不允许的。榆树不允许。
您可以使用 Maybe
类型模拟可变数量的不同类型的参数,将 Nothing
理解为 "missing argument":
updateRec : Rec -> Maybe Int -> Maybe Int -> Maybe Int -> Rec
updateRec r a b c =
{ r
| a = a |> Maybe.withDefault r.a
, b = b |> Maybe.withDefault r.b
, c = c |> Maybe.withDefault r.c
}
如果记录字段都是同一类型(此处 Int
),您可以接受 List Int
:
updateRec : Rec -> List Int -> Rec
updateRec r fields =
case fields of
[a] -> { r | a = a }
[a,b] -> { r | a = a, b = b }
[a,b,c] -> { r | a = a, b = b, c = c }
_ -> r
我不喜欢这个解决方案,因为如果您不小心提供了一个包含 0 或 4 个以上元素的列表,它会自动失败。如果这个函数无论如何对你有帮助,也许一开始就使用 List Int
而不是 Rec
会更好。
Elm 的记录更新语法似乎正是您要找的。您 "pass in" 您想要更新的记录,r
下面,您可以 return 一个包含您想要更改的任何字段的记录,而无需指定每个字段:
ex1 = { r|a = 1 }
ex2 = { r|b = 2, c = 3 }
您不需要创建一组附加函数来在特定时间仅更新特定字段,因为 Elm 的记录更新语法是那个通用函数。
这是做同样事情的更好方法:
updateA : Int -> Rec -> Rec
updateA x rec = { rec | a = x }
-- Similarly for b, c
现在您可以执行以下操作,假设您已经有一个要更新的值 rec : Rec
:
myUpdatedRec : Rec
myUpdatedRec =
rec
|> updateA 7
|> updateB 19
您现在可以通过将任意数量的字段串在一起来更新任意数量的字段 |> updateX ...
。
考虑
type alias Rec = { a: Int, b: Int, c:Int }
updateRec r aVal = { r|a = aVal }
updateRec2 r aVal bVal = { r|a = aVal, b= bVal }
updateRec3 r aVal bVal cVal = ...
如何将 updateRec
和 updateRec2
... 概括为一个函数?
您想编写一个具有可变数量的不同类型参数的函数。这在动态类型语言(Javascript、Python、Ruby)中很常见,但在类型语言中通常是不允许的。榆树不允许。
您可以使用 Maybe
类型模拟可变数量的不同类型的参数,将 Nothing
理解为 "missing argument":
updateRec : Rec -> Maybe Int -> Maybe Int -> Maybe Int -> Rec
updateRec r a b c =
{ r
| a = a |> Maybe.withDefault r.a
, b = b |> Maybe.withDefault r.b
, c = c |> Maybe.withDefault r.c
}
如果记录字段都是同一类型(此处 Int
),您可以接受 List Int
:
updateRec : Rec -> List Int -> Rec
updateRec r fields =
case fields of
[a] -> { r | a = a }
[a,b] -> { r | a = a, b = b }
[a,b,c] -> { r | a = a, b = b, c = c }
_ -> r
我不喜欢这个解决方案,因为如果您不小心提供了一个包含 0 或 4 个以上元素的列表,它会自动失败。如果这个函数无论如何对你有帮助,也许一开始就使用 List Int
而不是 Rec
会更好。
Elm 的记录更新语法似乎正是您要找的。您 "pass in" 您想要更新的记录,r
下面,您可以 return 一个包含您想要更改的任何字段的记录,而无需指定每个字段:
ex1 = { r|a = 1 }
ex2 = { r|b = 2, c = 3 }
您不需要创建一组附加函数来在特定时间仅更新特定字段,因为 Elm 的记录更新语法是那个通用函数。
这是做同样事情的更好方法:
updateA : Int -> Rec -> Rec
updateA x rec = { rec | a = x }
-- Similarly for b, c
现在您可以执行以下操作,假设您已经有一个要更新的值 rec : Rec
:
myUpdatedRec : Rec
myUpdatedRec =
rec
|> updateA 7
|> updateB 19
您现在可以通过将任意数量的字段串在一起来更新任意数量的字段 |> updateX ...
。