Reputation:
I have a some structure:
data S = {
a :: Integer,
b :: Integer,
c :: String,
d :: Map String Integer
}
I closed it in my State monad
, And I am using it in following way:
s <- get
let S {a = a', b =b', c=c', d=d'} s
put $ S {a = a' + 1, b = b', c= c', d = d'}
As you can see, when I would like to modify/read only one field (here a
), I must get and put all fields - it is embarassing - otherwise I get warnings and sometimes runtime errors.
Can you try to propose me some solution to make it better and cleaner ?
Thanks in advance,
Regards
Upvotes: 3
Views: 77
Reputation: 32319
You can use a record update and specify only the fields you want to update. Also, you can extract a particular field during pattern matching.
s@S{ a = a' } <- get
put $ s{ a = a' + 1 }
Alternately, if you find yourself doing a lot of this sort of thing, you might want to use lens
. With lens
, you would have to make lenses for S
(which requires turning on -XTemplateHaskell
)
data S = { _a, _b :: Integer, _c :: String, _d :: Map String Integer }
makeLenses ''S
But then, in your state monad you can just write
a += 1
Yep, this is legitimate Haskell. +=
is actually a thing.
Upvotes: 7