如何只修改记录的一个字段而不完全重写它?
How to modify just one field of a record without rewriting it completely?
这是我第二次处理这个问题...这是我第二次处理 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 解决方案是什么?有什么方法可以让我不重写所有未更改的字段?
你可以这样写更新:
oldrecord { somefield = newvalue }
所以在你的情况下,你可以这样写:
let incrementCounter cs@(CurrentState{bar=<b>b</b>}) = <b>cs {bar = b+1}</b>
您还可以使用 lens
进行更高级的更新。
这是我第二次处理这个问题...这是我第二次处理 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 解决方案是什么?有什么方法可以让我不重写所有未更改的字段?
你可以这样写更新:
oldrecord { somefield = newvalue }
所以在你的情况下,你可以这样写:
let incrementCounter cs@(CurrentState{bar=<b>b</b>}) = <b>cs {bar = b+1}</b>
您还可以使用 lens
进行更高级的更新。