考虑类型为 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)
这实现了无点样式,并且添加参数很简单 - 但它们前置在左侧而不是附加在右侧,因此您失去了与函数类型的对应关系(a -> b -> c)
。此外,如果参数更多,您最终会得到比第一个实现中仅使用 lambda 更长的表达式。
那么,有没有好的、简洁的方式来编写我想要的部分,或者我是否坚持使用 lambda?
最佳答案
<*>
对 <$>
的结果进行运算,所以:
g = (<*> a2) . (<$> a1)
关于haskell - 适用于 <$> 和 <*> 的运算符部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30748319/