如何在不完全重写记录的情况下仅修改记录的一个字段? [英] How to modify just one field of a record without rewriting it completely?

查看:102
本文介绍了如何在不完全重写记录的情况下仅修改记录的一个字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

It's the second time I'm tackling this problem... And for the second time this is while working with the State monad, apparently a state likes to consist of many fields, not just one

我有一个元组:

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

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

Assume a simple transformation of this tuple is needed... The second Int is a sort of counter, it needs to be incremented:

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

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

Wow. Lots of typing. Now since incrementing the counter is not the only possible operation of this tuple, then clearly there will be many more functions of this kind... The clutter soon becomes annoying.

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

And what if we change the tuple to a record?

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

现在增加计数器就更糟了!

Incrementing the counter is now even worse!

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解决方案是什么?有什么办法可以让我不重写所有不变的字段?

This is kind of amazing. All I want to do is what I'd write in an imperative language as currState.bar += 1;. What is the typical Haskell solution for this kind of problems? Is there any way that would allow me to not rewrite all fields that don't change?

推荐答案

您可以编写如下更新:

oldrecord { somefield = newvalue }

因此,在您的情况下,您可以这样写:

so in your case, you can write it like:

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

您还可以使用 lens 来获取更多信息高级更新.

You can also make use of lens for more advanced updates.

这篇关于如何在不完全重写记录的情况下仅修改记录的一个字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆