haskell - 如何组合镜头和仿函数?

标签 haskell lenses haskell-lens

我正在努力适应 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

这将允许您获取(使用 previewtoListOf )并在 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/

相关文章:

haskell - gtk 和 gtk2 之间的区别

haskell - 使用带有镜头的一元函数修改状态

haskell - 镜头 : zooming newtype

haskell - 这是 Template Haskell 的预期行为吗?

haskell - .~ 的 Monadic 版本(Haskell)

haskell - 无法运行在 GHCI 中运行的我的 wxHaskell 程序

Haskell 简化技术和 monad

haskell - GHC 的 Int 类型的位大小

scala - 在深度复制到 Map 值时避免重复使用镜头

haskell - 为什么我不能像普通变量一样绑定(bind)和重用 haskell 透镜?