如何编写更新Record字段的通用函数

时间:2016-05-05 05:03:59

标签: field record elm

考虑

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 = ...

如何将updateRecupdateRec2 ...概括为一个函数?

3 个答案:

答案 0 :(得分:2)

您想编写一个具有可变数量的不同类型参数的函数。这在动态类型语言(Javascript,Python,Ruby)中很常见,但通常不允许使用类型语言。榆树不允许这样做。

您可以使用Maybe类型模拟可变数量的不同类型参数,将Nothing理解为"缺少参数":

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

答案 1 :(得分:2)

这是做同样事情的更好方法:

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 ...串联起来来更新任意数量的字段。

答案 2 :(得分:1)

Elm的记录更新语法似乎正是您正在寻找的。你"传入"您想要更新的记录,r,您可以返回包含您想要更改的字段的记录,而无需指定每个字段:

ex1 = { r|a = 1 }
ex2 = { r|b = 2, c = 3 }

您不需要创建一组附加功能,以便在特定时间仅更新某些字段,因为Elm的记录更新语法那个通用功能。