如何在更新少数时避免引用所有状态变量? [英] How do I avoid referring to all state variables when updating only a few?

查看:83
本文介绍了如何在更新少数时避免引用所有状态变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  p1 :: State() Int,String)()
p1 = do
(a,b)< - get
...做某事...
put(a',b)

p2 :: State(Int,String)()
p2 = do
(a,b)< - get
...做别的事.. 。
put(a,b')

main = do
...初始化a0 b0 ...
print。翻转evalState(a0,b0)
。然而,随着状态变量的数量增加,这个快速的获得比所需更详细的方式:
$ b $ pre $ p $ :: State(Int,String,Bool,Int,String,Bool)()
p1 = do
(a,b,c,d,e,f)< - get
...做某事...
put(a,b, c',d,e,f')

p2 :: State(Int,String,Bool,Int,String,Bool)()
p2 = do
,b,c,d,e,f)< - get
...做某事...
put(a',b',c,d,e,f)

main =做
打印。 flip evalState(a0,b0,c0,d0,e0,f0)
。序列$ replicate 10 p1 ++ repeat p2

我想知道,是否有更新的方法几个状态变量不必参考所有未使用的变量?我正在考虑类似于 IORef ,但是对于 State (实际上有一个包 stateref ),但我不确定是否已经有其他人已经使用过的一些常见成语。

解决方案

对于透镜的。特别是 控制。 Lens.Tuple 模块连同。= 使用



  p1 = do 
a < - 使用_1
- 做某事 -
_1。 = a'

但是,如果您以状态专有名称给出事物通常会更好,例如

  { - #LANGUAGE TemplateHaskell# -  

data Record = MkRecord {_age :: Int
,_name :: String
,_programmer :: Bool
}派生(Show,Eq)
makeLenses''记录

通过这种方式,您可以为自己的领域提供更好的名称:

  p1 =做
a< - 使用年龄
- 做某事 -
年龄。= a'

请注意,如果您不wa,这仍然有助于您nt使用镜头,因为您可以使用记录语法来更新您的数据:

  p1 = do 
r< - get
let a = _age r
---做某事
放$ r {_age = a'}


An idiom I use for composing a couple of procedures (with memory) is as follows:

p1 :: State (Int, String) ()
p1 = do
    (a, b) <- get
    ... do something ...
    put (a', b)

p2 :: State (Int, String) ()
p2 = do
    (a, b) <- get
    ... do something else ...
    put (a, b')

main = do
    ... initializing a0 b0 ...
    print . flip evalState (a0, b0)
          . sequence $ replicate 10 p1 ++ repeat p2

However, as the number of state variable grows, this quickly gets way more verbose than necessary:

p1 :: State (Int, String, Bool, Int, String, Bool) ()
p1 = do
    (a, b, c, d, e, f) <- get
    ... do something ...
    put (a, b, c', d, e, f')

p2 :: State (Int, String, Bool, Int, String, Bool) ()
p2 = do
    (a, b, c, d, e, f) <- get
    ... do something ...
    put (a', b', c, d, e, f)

main = do
    print . flip evalState (a0, b0, c0, d0, e0, f0)
          . sequence $ replicate 10 p1 ++ repeat p2

As I was wondering, is there a way of updating only a few state variables without having to refer to all the unused ones? I was thinking something like IORef but for State (in fact there is a package stateref), but I'm not sure if there are already some common idioms that other people have been using.

解决方案

This seems like a job for lenses. Especially the Control.Lens.Tuple module together with .= and use:

p1 = do
   a <- use _1
   -- do something --
   _1 .= a'

However, it's usually better if you give the things in your state proper names, e.g.

{-# LANGUAGE TemplateHaskell #-

data Record = MkRecord { _age :: Int
                       , _name :: String
                       , _programmer :: Bool
                       } deriving (Show, Eq)
makeLenses ''Record

That way, you have better names for your field:

p1 = do
   a <- use age
   -- do something --
   age .= a'

Note that this still helps you if you don't want to use lenses, since you can use record syntax to update your data:

 p1 = do
      r <- get
      let a = _age r
      --- do something
      put $ r{_age = a'}

这篇关于如何在更新少数时避免引用所有状态变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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