【问题标题】:Eliminating `flip` in Haskell lens消除 Haskell 镜头中的“翻转”
【发布时间】:2021-08-09 16:47:07
【问题描述】:

我正在尝试掌握镜头的窍门。有没有更惯用的方式来编写以下内容? (下划线前的占位符)

flip (set _lens) _a . fmap _f

对我来说,flip 的使用似乎暗示了非惯用代码。在这种情况下是否有更好的组合器可以避免flip?有没有更类似镜头的方式来整合fmap?

【问题讨论】:

  • 如果你扩展/完成这个例子会更容易回答。

标签: haskell idioms haskell-lens lenses


【解决方案1】:

在这种情况下,你可能要考虑写它指向

\x -> _a & _lens .~ fmap _f x

这对我来说更习惯了。

如果你真的想要没有flip的pointfree,你可以将上面的转换为pointfree:

(_a &) . set _lens . fmap _f

(虽然从技术上讲,由于& 等同于flip ($),你实际上只是隐藏了flip。)

【讨论】:

  • 我的结论是,我没有什么严重的遗漏。
【解决方案2】:

我认为@DDub 已经涵盖了您问题的前半部分。至于集成fmap 的更“类似镜头”的方式,这似乎是更普遍问题的特例。如果我有二传手:

> (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

结合_lensfmap _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")

一定会让你的朋友大吃一惊。

【讨论】:

  • 我想我的朋友会说,那不是英语,而且有很多标点符号... :->
猜你喜欢
  • 1970-01-01
  • 2021-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 2020-03-08
  • 2012-01-14
相关资源
最近更新 更多