如何使用镜头对某些状态下的序列执行只读monadic操作?

Bar*_*icz 4 haskell haskell-lens

我的数据结构看起来或多或少像这样(为了问题的目的简化)

data GameObject = GameObject { _num :: Int }
data Game = Game { _objects :: [GameObject] }
Run Code Online (Sandbox Code Playgroud)

我用它makeLenses来为这两者生成访问器.因此,我能够像这样集体进行操作:

-- loop :: MonadState with Game inside
loop = objects.traversed.num += 1
Run Code Online (Sandbox Code Playgroud)

这很棒.


但是,我找不到相应的方法(打印每一个num):

game <- get
let objects = _objects game
let objectNums = map _num objects
mapM_ print objectNums
Run Code Online (Sandbox Code Playgroud)

我尝试过类似的东西

uses (objects.traversed.num) >>= mapM_ print
Run Code Online (Sandbox Code Playgroud)

但我认为使用traversed某种状态的唯一方法就是使用幺半群,我不想将这些字段组合在一起; 我想对来自我的状态中的某些序列的元素中的每个元素的一部分运行monadic动作.

那么,这可能是使用一些提供的镜头功能,还是我必须自己编写,不知何故?

kos*_*kus 6

关于什么

mapMOf_ (objects . traversed . num) print
Run Code Online (Sandbox Code Playgroud)

或者如果你想将它应用于州monad的状态,

get >>= mapMOf_ (objects . traversed . num) print
Run Code Online (Sandbox Code Playgroud)

?(也许有一种更像镜头的方式将第一行与州monad的状态结合起来.如果是这样,我想亲自了解它.)