我正在努力适应 lens
Haskell 的库,发现自己在一些简单的问题上苦苦挣扎。例如,假设(为方便起见)at
和 _1
有以下类型(至少我是这样理解它们的):
at :: Ord k => k -> Lens' (Map k v) (Maybe v)
_1 :: Lens' (a, b) a
如何将这些镜头组合成具有以下类型的镜头:
maybeFst :: Ord k => k -> Lens' (Map k (a, b)) (Maybe a)
最佳答案
你想要一个像这样的镜头
Lens' (Maybe (a, b)) (Maybe a)
但这不可能是
Lens
自从放回Nothing
影响 b
也是。可以是 Getter
getA :: Getter (Maybe (a, b)) (Maybe a)
getA = to (fmap fst)
但是当你编写它时,你会得到一个
Getter
同样,不是完整的Lens
maybeFst :: Ord k => k -> Getter (Map k (a, b)) (Maybe a)
maybeFst k = at k . getA
可能比这更好的是使用
Traversal
反而maybeFstT :: Ord k => k -> Traversal' (Map k (a, b)) a
maybeFstT k = at k . _Just . _1
这将允许您获取(使用
preview
或 toListOf
)并在 fst
处设置值 map 中的值,但您将无法修改其在 map 中的存在:如果该值不存在,则无法添加它,如果存在则无法删除它。最后,我们可以陪审团造假
Lens
它具有适当的类型,尽管我们必须给它一个默认值 b
getA :: b -> Lens' (Maybe (a, b)) (Maybe a)
getA b inj Nothing = (\x -> (,b) <$> x) <$> inj Nothing
getA _ inj (Just (a, b)) = (\x -> (,b) <$> x) <$> inj (Just a)
但请注意,它有一些不太 -
Lens
喜欢的行为。>>> Just (1, 2) & getA 0 .~ Nothing & preview (_Just . _2)
Nothing
>>> Nothing & getA 0 .~ Just 1
Just (1,0)
所以通常最好避免使用这些伪透镜以防止发生意外。
关于haskell - 如何组合镜头和仿函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22363189/