消除 Haskell 镜头中的“翻转”
Eliminating `flip` in Haskell lens
我正在尝试掌握镜头的窍门。是否有更惯用的方式来编写以下内容? (占位符前面有下划线)
flip (set _lens) _a . fmap _f
对我来说,flip
的使用似乎暗示了非惯用代码。在这种情况下是否有更好的组合器可以避免 flip
?有没有更像镜头的方式来整合 fmap?
在这种情况下,你可能要考虑把它写成尖的
\x -> _a & _lens .~ fmap _f x
这对我来说更加地道。
如果你真的想要没有flip
的pointfree,你可以将上面的转换为pointfree:
(_a &) . set _lens . fmap _f
(尽管从技术上讲,由于 &
等同于 flip ($)
,您实际上只是隐藏了 flip
。)
我认为@DDub 已经涵盖了你问题的前半部分。至于集成 fmap
的更“类似镜头”的方式,这似乎是更普遍问题的特例。如果我有 setter:
> (1,"a") & _1 .~ True
(True,"a")
那么我认为应该有一个允许我写的组合器:
> (1,"a") & _1 . applying not .~ True
(False,"a")
这个组合子 似乎 不存在于 lens
中(除非其他人可以发现它),但您可以将其定义为:
applying :: Functor f => (a -> b) -> (c -> f a) -> (c -> f b)
applying f = (fmap f .)
或使用 Functor
实例 (->) r
:
applying :: Functor f => (a -> b) -> (c -> f a) -> (c -> f b)
applying = fmap . fmap
这导致了一个有趣的事实,即 setter:
_lens . (fmap . fmap . fmap) _f
将 _lens
与 fmap _f
的应用相结合,因此以下产生等效的结果:
ex1 = (flip (set _1) ("a","b") . fmap not) $ Just True
ex2 = ("a","b") & _1 . applying (fmap not) .~ Just True
ex3 = ("a","b") & _1 . (fmap . fmap . fmap) not .~ Just True
-- all the above yield: (Just False,"b")
一定会让您的朋友大吃一惊。
我正在尝试掌握镜头的窍门。是否有更惯用的方式来编写以下内容? (占位符前面有下划线)
flip (set _lens) _a . fmap _f
对我来说,flip
的使用似乎暗示了非惯用代码。在这种情况下是否有更好的组合器可以避免 flip
?有没有更像镜头的方式来整合 fmap?
在这种情况下,你可能要考虑把它写成尖的
\x -> _a & _lens .~ fmap _f x
这对我来说更加地道。
如果你真的想要没有flip
的pointfree,你可以将上面的转换为pointfree:
(_a &) . set _lens . fmap _f
(尽管从技术上讲,由于 &
等同于 flip ($)
,您实际上只是隐藏了 flip
。)
我认为@DDub 已经涵盖了你问题的前半部分。至于集成 fmap
的更“类似镜头”的方式,这似乎是更普遍问题的特例。如果我有 setter:
> (1,"a") & _1 .~ True
(True,"a")
那么我认为应该有一个允许我写的组合器:
> (1,"a") & _1 . applying not .~ True
(False,"a")
这个组合子 似乎 不存在于 lens
中(除非其他人可以发现它),但您可以将其定义为:
applying :: Functor f => (a -> b) -> (c -> f a) -> (c -> f b)
applying f = (fmap f .)
或使用 Functor
实例 (->) r
:
applying :: Functor f => (a -> b) -> (c -> f a) -> (c -> f b)
applying = fmap . fmap
这导致了一个有趣的事实,即 setter:
_lens . (fmap . fmap . fmap) _f
将 _lens
与 fmap _f
的应用相结合,因此以下产生等效的结果:
ex1 = (flip (set _1) ("a","b") . fmap not) $ Just True
ex2 = ("a","b") & _1 . applying (fmap not) .~ Just True
ex3 = ("a","b") & _1 . (fmap . fmap . fmap) not .~ Just True
-- all the above yield: (Just False,"b")
一定会让您的朋友大吃一惊。