【问题标题】:Operator section for applicative with <$> and <*>适用于 <$> 和 <*> 的运算符部分
【发布时间】:2015-08-25 05:33:55
【问题描述】:

考虑a -&gt; b -&gt; c 类型的函数和应用值a1, a2 :: (Applicative f) =&gt; f a

我希望构造一个函数,该函数可应用于a -&gt; b -&gt; c 类型的函数以获得Applicative f :: f c 类型的值。我可以通过以下方式做到这一点:

g :: (Applicative f) => (a -> b -> c) -> f c
g = \f -> f <$> a1 <*> a2

(显式 lambda 是经过深思熟虑的,因为我正在考虑在任何级别构建此函数,而不仅仅是顶层)。

如果我尝试以无点风格写g

g = (<$> a1 <*> a2)

我得到以下编译错误:

The operator `<$>' [infixl 4] of a section
    must have lower precedence than that of the operand,
      namely `<*>' [infixl 4]
    in the section: `<$> gen1 <*> gen2'

可以编写这个无点实现:

g = flip (flip liftA2 a1) a2

但我觉得这不太可读,并且将基于中缀函数的实现重构为例如添加另一个参数比将上面更改为使用liftA3更简单。

一个人可以写出一连串的作品:

g = (<*> a2) . (<$> a1)

这实现了无点样式并且添加参数很简单 - 但是它们在左侧而不是在右侧附加 prepended,因此您失去了与函数类型 (a -&gt; b -&gt; c) 的对应关系.此外,与在第一个实现中仅使用 lambda 相比,使用更多参数最终会得到更长的表达式。

那么,有没有很好、简洁的方法来编写我想要的部分,还是我坚持使用 lambda?

【问题讨论】:

  • 在 Scala 中你可以有 _ &lt;$&gt; a &lt;*&gt; b 但 Haskell 没有这样的语法。
  • @ErikAllik 这是很有趣的语法!我想知道是否有人为它写了一个模板-haskell 扩展。那太好了。
  • 但是_已经被打孔了;也许类似的东西;虽然 lambda 语法很好。

标签: haskell applicative operator-sections


【解决方案1】:

&lt;*&gt;&lt;$&gt; 的结果进行运算,所以:

g = (<*> a2) . (<$> a1)

【讨论】:

  • @frasertweedale:在这种情况下,我会使用你的第一种方法。不过,它并不是必须是 lambda。 g f = f &lt;$&gt; a1 &lt;*&gt; a2
  • @frasertweedale:即使不只是顶层,你也可以使用let 等。更少的冗长并不意味着更清晰。
【解决方案2】:

我不太相信 pointfree 可以比在这里使用显式参数更好,但还有一些想法:

  • 你可以使用flip中缀:

    g = liftA2 `flip` a1 `flip` a2
    
  • 你可以使用Control.Category中的&gt;&gt;&gt;,也就是.翻转:

    g = (<$> a1) >>> (<*> a2)
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-04
    • 1970-01-01
    • 2020-12-01
    • 2014-10-27
    • 1970-01-01
    • 2018-02-24
    • 2018-08-20
    • 1970-01-01
    相关资源
    最近更新 更多