在Haskell中使用Lens来修改值

时间:2014-01-13 05:00:40

标签: haskell lenses lens

我经常发现自己使用这种模式:

do
    let oldHeaders = mail ^. headers
    put $ (headers .~ (insert header value oldHeaders)) mail

这似乎是Control.Lens应该能够做的事情,但我想我还没有找到合适的运算符。有没有更好的办法?另外,在这段代码中我还应该做些什么吗?

2 个答案:

答案 0 :(得分:11)

您可以使用Lens es和Traversal链直接访问内部标头值并进行更新。

put $ mail & headers . at header ?~ value

请注意,(?~)只是\lens value -> lens .~ Just value的简写。需要Justat镜头表明我们想要插入一个值(如果它已经不存在)。

如果第一行中的mail来自状态monad,就像这样

do
  mail <- get
  let oldHeaders = mail ^. headers
  put $ (headers .~ (insert header value oldHeaders)) mail

然后用modify :: MonadState s m => (s -> s) -> m ()

写出来更简单
modify (headers . at header ?~ value)

正如ØrjanJohansen在评论中所建议的那样,可以写成最简洁的

headers . at header ?= value

答案 1 :(得分:7)

使用镜头时,get monad中通常不需要putState。在您的情况下,您可以使用运算符?=直接更新状态:

example = do
  headers . at header ?= value

您还可以使用%=修改任何具有功能的镜头:

example2 = do
  headers %= insert header value