【发布时间】:2015-08-25 05:33:55
【问题描述】:
考虑a -> b -> c 类型的函数和应用值a1, a2 :: (Applicative f) => f a。
我希望构造一个函数,该函数可应用于a -> b -> 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 -> b -> c) 的对应关系.此外,与在第一个实现中仅使用 lambda 相比,使用更多参数最终会得到更长的表达式。
那么,有没有很好、简洁的方法来编写我想要的部分,还是我坚持使用 lambda?
【问题讨论】:
-
在 Scala 中你可以有
_ <$> a <*> b但 Haskell 没有这样的语法。 -
@ErikAllik 这是很有趣的语法!我想知道是否有人为它写了一个模板-haskell 扩展。那太好了。
-
但是
_已经被打孔了;也许类似的东西;虽然 lambda 语法很好。
标签: haskell applicative operator-sections