我还没有完全了解镜头。
applicationState = (
'a',
'b',
( M.fromList $ zip [1..3] [11,22,33],
M.fromList $ zip [4,5,6] [44,55,66],
M.fromList $ zip [7,8,9] [M.fromList $ zip [2,3,4] ["77","777","7777"],
M.fromList $ zip [2,3,4] ["88","888","8888"],
M.fromList $ zip [2,3,4] ["99","999","9999"]] )
)
是否有更多镜头惯用的方法:
λ> view (_3 . _3 . at 9) applicationState >>= view (at 4) >>= return . ('9':)
Just "99999"
答案 0 :(得分:2)
您可以使用traverse :: Traversal (Maybe a) (Maybe b) a b
,然后使用preview
:
preview (_3 . _3 . at 9 . traverse . at 4 . traverse . to ('9':)) applicationState
因为ix i = at i . traverse
,这也可以写成:
preview (_3 . _3 . ix 9 . ix 4 . to ('9':)) applicationState
您也可以修改这种方式,但如果at
中的任何一个失败,则不会更改任何内容(您无法使用Traversal
在地图中插入新元素)。
另一种方法是使用non :: a -> Lens' (Maybe a) a
。仅当第一个地图(由镜头_3._3
访问)从不包含空地图作为值而第二个地图永远不包含空字符串作为值时,此方法才有效。因此,以下值对applicationState无效:
('a', 'b',
( M.fromList $ zip [1..3] [11,22,33]
, M.fromList $ zip [4,5,6] [44,55,66]
, M.fromList $ zip [7..9] [M.empty] -- No value of this map may be the empty map
)
)
使用non
,您的示例可以写为:
view (_3 . _3 . at 9 . non M.empty . at 4 . non "" . to ('9':)) applicationState
这也允许通过设置插入新条目(如果您设置并且键4或9尚未存在,它们将被创建)并删除条目(如果您设置为值"&# 34;,键4将被移除,如果在移除该键后地图为空,则键9也将被移除)。