我如何使用Control.Lens更新列表的第i个元素? [英] How can I use Control.Lens to update the ith element of a list?

查看:122
本文介绍了我如何使用Control.Lens更新列表的第i个元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  data数据Outer = Outer {_list :: [Inner]} 
数据Inner = Inner {_bool :: Bool}

使用Control.Lens,我可以访问_bool (这是一个'State Outer'monad内部)像这样

  boolValue<  -  gets(^。list。to (!! i)。inner)

我也希望能够用一些东西来更新这个值像

  list ^。 (to(!! i))^。内心%=真

然而(据我了解),'to'函数只创建一个getter,不是一个真正的镜头,可以用作吸气剂或吸气剂。



那么,我该如何将(!! i)转换成一个镜头来让我更新这个领域?

解决方案

你不能将(!!)变成除 Getter - 但有一个函数可以做这样的事情: ix ,以访问索引处的内容。它实际上是一个遍历,而不是 Lens - 在这里,这意味着它可能失败(如果索引是超出界限的) - 但只要索引在列表中,它就可以工作。



还有一个问题,即 - (^。)也是专门用于获取值的运算符。它与例如不兼容(%=),它将镜头般的东西当作第一个参数。和:(%=)用于将函数映射到现有值;如果你只是想设置,你可以使用(。=)。所以你可能想要这样的东西:

  list。 ix i。 inner。= True 

*实际上有一个函数可以做到这一点 - 它被称为 - 但它使用美妙的邪恶黑魔法,你不应该使用它,至少不是用于这个(也可能不适用于任何真正的代码)。


I have some datatypes along the line of

data Outer = Outer { _list :: [ Inner ] }
data Inner = Inner { _bool :: Bool }

using Control.Lens, I can access the _bool of the ith Inner (inside a 'State Outer' monad) like this

boolValue <- gets (^. list . to (!! i) . inner)

I would like to also be able to update this value with something like

list ^. (to (!! i)) ^. inner %= True

However (by my understanding), the 'to' function only creates a getter, not a true lens that can be used as either getter or setter.

So, how can I convert (!! i) into a lens that will allow me to update this field?

解决方案

You can't* turn (!!) into any lens-like thing other than a Getter -- but there's a function to do this sort of thing: ix, for accessing things at indices. It's actually a Traversal, not a Lens -- which, here, just means that it can fail (if the index is out of bounds) -- but as long as the index is in the list, it'll work.

There's another problem, though -- (^.) is also an operator that's used exclusively for getting values. It's incompatible with e.g. (%=), which takes a lens-like thing as its first argument. And: (%=) is for mapping a function over the existing value; if you just want to set, you can use (.=). So you probably want something like:

list . ix i . inner .= True

* There actually is a function that can do this -- it's called upon -- but it uses wonderful evil black magic and you shouldn't use it, at least not for this (and probably not for any real code).

这篇关于我如何使用Control.Lens更新列表的第i个元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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