用于嵌套容器的索引透镜
Indexed lenses for nested containers
如何使用lens获取多级嵌套的key?
考虑以下类型
data Outer = Outer { _outerMap :: Map String Inner }
data Inner = Inner { _innerMap :: Map Char Int }
makeLenses ''Outer
makeLenses ''Inner
并假定以下示例值
example :: Outer
example = Outer $ Map.fromList
[ ("A", Inner $ Map.fromList [ ('a', 1), ('b', 2), ('c', 3) ])
, ("B", Inner $ Map.fromList [ ('a', 4), ('b', 6), ('c', 8) ])
, ("C", Inner $ Map.fromList [ ('a', 5), ('b', 7), ('c', 9) ])
]
使用镜头我可以将 example
展平为 [Int]
并按如下方式过滤奇数:
>>> example^..outerMap.folded.innerMap.folded.filtered odd
[1,3,5,7,9]
我可以用内键注释值如下:
>>> example^@..outerMap.folded.innerMap.ifolded.filtered odd
[('a',1),('c',3),('a',5),('b',7),('c',9)]
但是我怎样才能使用镜头来注释外键和内键的值,以获得以下结果?
>>> _whatHere example
[(("A",'a'),1),(("A",'c'),3),(("C",'a'),5),(("C",'b'),7),(("C",'c'),9)]
下面的尝试仍然只有returns内键:
>>> example^@..outerMap.ifolded.innerMap.ifolded.filtered odd
[('a',1),('c',3),('a',5),('b',7),('c',9)]
并且以下尝试不进行类型检查
>>> example^..outerMap.ifolded.withIndex.alongside id (innerMap.ifolded.filtered odd.withIndex)
error:
• No instance for (Applicative
(Control.Lens.Internal.Getter.AlongsideRight
(Const (Data.Monoid.Endo [([Char], (Char, Int))])) [Char]))
没有镜头的实现可能看起来像这样:
nolens :: Outer -> [((String, Char), Int)]
nolens =
filter (odd . snd)
. foldMap (\(k, i) -> (map (first (k, )) . Map.toList . _innerMap) i)
. Map.toList
. _outerMap
使用(<.>)
。它就像 (.)
,只是它保留了左右两边的索引。 (.)
本身(及其别名 (.>)
)仅保留 RHS 的索引,除非 RHS 本身是保留索引的,在这种情况下,索引来自 LHS。助记符是箭头指向您要保存的索引。
>>> example^@..outerMap.ifolded<.>innerMap.ifolded.filtered odd
[(("A",'a'),1),(("A",'c'),3),(("C",'a'),5),(("C",'b'),7),(("C",'c'),9)]
如何使用lens获取多级嵌套的key?
考虑以下类型
data Outer = Outer { _outerMap :: Map String Inner }
data Inner = Inner { _innerMap :: Map Char Int }
makeLenses ''Outer
makeLenses ''Inner
并假定以下示例值
example :: Outer
example = Outer $ Map.fromList
[ ("A", Inner $ Map.fromList [ ('a', 1), ('b', 2), ('c', 3) ])
, ("B", Inner $ Map.fromList [ ('a', 4), ('b', 6), ('c', 8) ])
, ("C", Inner $ Map.fromList [ ('a', 5), ('b', 7), ('c', 9) ])
]
使用镜头我可以将 example
展平为 [Int]
并按如下方式过滤奇数:
>>> example^..outerMap.folded.innerMap.folded.filtered odd
[1,3,5,7,9]
我可以用内键注释值如下:
>>> example^@..outerMap.folded.innerMap.ifolded.filtered odd
[('a',1),('c',3),('a',5),('b',7),('c',9)]
但是我怎样才能使用镜头来注释外键和内键的值,以获得以下结果?
>>> _whatHere example
[(("A",'a'),1),(("A",'c'),3),(("C",'a'),5),(("C",'b'),7),(("C",'c'),9)]
下面的尝试仍然只有returns内键:
>>> example^@..outerMap.ifolded.innerMap.ifolded.filtered odd
[('a',1),('c',3),('a',5),('b',7),('c',9)]
并且以下尝试不进行类型检查
>>> example^..outerMap.ifolded.withIndex.alongside id (innerMap.ifolded.filtered odd.withIndex)
error:
• No instance for (Applicative
(Control.Lens.Internal.Getter.AlongsideRight
(Const (Data.Monoid.Endo [([Char], (Char, Int))])) [Char]))
没有镜头的实现可能看起来像这样:
nolens :: Outer -> [((String, Char), Int)]
nolens =
filter (odd . snd)
. foldMap (\(k, i) -> (map (first (k, )) . Map.toList . _innerMap) i)
. Map.toList
. _outerMap
使用(<.>)
。它就像 (.)
,只是它保留了左右两边的索引。 (.)
本身(及其别名 (.>)
)仅保留 RHS 的索引,除非 RHS 本身是保留索引的,在这种情况下,索引来自 LHS。助记符是箭头指向您要保存的索引。
>>> example^@..outerMap.ifolded<.>innerMap.ifolded.filtered odd
[(("A",'a'),1),(("A",'c'),3),(("C",'a'),5),(("C",'b'),7),(("C",'c'),9)]