如何仅修改记录的一个字段而不完全重写它?

时间:2019-04-24 20:22:56

标签: haskell tuples variable-assignment record

这是我第二次解决这个问题... 第二次是在与State monad一起工作时,显然一个州喜欢由许多领域组成,而不仅仅是一个领域

我有一个元组:

type CurrentState = (Int, Int, String, [Int], CustType1, CustType2, CustType3 )

假设需要对该元组进行简单的转换...第二个Int是一种计数器,它需要增加:

let incrementCounter currState@(foo, bar, baz, fizz, buzz, blah, yadda) =
    ( foo, bar+1, baz, fizz, buzz, blah, yadda )

哇。很多打字。现在,既然增加计数器并不是该元组的唯一可能操作,那么显然会有更多此类功能……混乱很快就会变得烦人。

如果将元组更改为记录怎么办?

data CurrentState = CurrentState { foo :: Int, bar :: Int, baz :: String,
                                   fizz :: [Int], buzz :: CustType1,
                                   blah :: CustType2, yadda :: CustType 3 }

增加计数器现在变得更糟!

let incrementCounter currState =
    CurrentState { foo = foo currState, bar = (bar currState) + 1,
                   baz = baz currState, fizz = fizz currState,
                   buzz = buzz currState, blah = blah currState,
                   yadda = yadda currState }

这太神奇了。我要做的就是用命令式语言currState.bar += 1;编写的内容。解决此类问题的典型Haskell解决方案是什么?有什么办法可以让我不重写所有不变的字段?

1 个答案:

答案 0 :(得分:5)

您可以编写如下更新:

oldrecord { somefield = newvalue }

因此,您可以这样写:

let incrementCounter cs@(CurrentState{bar=b}) = cs {bar = b+1}

您还可以使用lens进行更高级的更新。