使用镜头通过索引访问矢量元素

时间:2015-03-25 22:30:06

标签: haskell vector lens

我正在寻找一种使用镜头库来引用矢量元素的方法......

让我试着用我的代码的简化示例来解释我想要实现的目标。

我在这个monad变换器堆栈中工作(其中StateT是焦点,其他一切都不重要)

newtype MyType a = MyType (StateT MyState (ExceptT String IO) a)

MyState 有很多字段,但其中一个是客户端的向量,它是我定义的数据类型:

data MyState = MyState { ...
                       , _clients :: V.Vector ClientT
                       }

每当我需要访问我的一个客户时,我倾向于这样做:

import Control.Lens (use)

c <- use clients
let neededClient = c V.! someIndex
... -- calculate something, update client if needed
clients %= (V.// [(someIndex, updatedClient)])

现在,我正在寻找的是:我希望我的功能能够获得&#34;参考&#34;对我感兴趣并使用它的客户(从State检索它,如果需要更新它)。

为了清楚我的意思,这里是一个片段(即使在伪代码中也不会编译):

...
myFunction (clients.ix 0)
...

myFunction clientLens = do
    c <- use clientLens -- I would like to access a client in the vector
    ... -- calculate stuff
    clientLens .= updatedClient

基本上,我想从镜头库传递给myFunction一些东西(我不知道我在这里经过什么......镜头?遍历?得到?其他一些东西?)这将允许我指向保存在StateT中的向量中的特定元素。它可能吗?目前,当使用&#34; clients.ix 0&#34;我收到一个错误,我的ClientT不是Monoid的实例。

这是我所拥有的非常愚蠢的版本。为了回答问题&#34;为什么我需要这种方式&#34;需要更多解释。如果有可能通过这个&#34;参考&#34;我感兴趣这将指向我的矢量中保存在状态中的某个元素。

1 个答案:

答案 0 :(得分:3)

clients.ix 0是一次遍历。特别是,遍历是设置器,因此设置和修改应该可以正常工作:

clients.ix 0 .= updatedClient

您的问题出在use。因为遍历并不一定只包含一个值,所以当您use遍历(或使用其他一些其他getter函数)时,它会结合所有值,假设它们是Monoid类型

特别是

use (clients.ix n)
如果mempty超出范围,

会希望返回n

相反,您可以使用preuse函数,该函数会丢弃除遍历的第一个目标之外的所有目标(或更常见的是折叠),并将其包装在{{1 }}。 E.g。

Maybe

请注意,如果Just c <- preuse (clients.ix n) 超出界限,则会出现模式匹配错误,因为n会返回preuse