考虑类型a -> b -> c
的函数和应用值a1, a2 :: (Applicative f) => f a
。
我希望构造一个函数,该函数可应用于 type 函数a -> b -> c
以获得 type 的值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
但我觉得这不太可读,重构基于函数的中缀实现更简单,例如,添加另一个参数,而不是将上面的内容更改为 use liftA3
。
一个人可以写出一系列的作品:
g = (<*> a2) . (<$> a1)
这实现了无点样式,并且添加参数很简单 - 但它们被添加到左侧而不是添加到右侧,因此您失去了与函数类型的对应关系(a -> b -> c)
。此外,与在第一个实现中仅使用 lambda 相比,使用更多参数最终会得到更长的表达式。
那么,是否有很好、简洁的方式来编写我想要的部分,还是我坚持使用 lambda?