Consider functions of the type a -> b -> c and applicative values a1, a2 :: (Applicative f) => fa .
I want to build a function that can be applied to functions of type a -> b -> c to get values ββof type Applicative f :: fc . I can do it like this:
g :: (Applicative f) => (a -> b -> c) -> fc g = \f -> f <$> a1 <*> a2
(Explicit lambda is intentional, as I am considering building this function at any level, not just at the top level).
If I try to write g in point-free style:
g = (<$> a1 <*> a2)
I get the following compilation error:
The operator `<$>' [infixl 4] of a section must have lower precedence than that of the operand, namely `<*>' [infixl 4] in the section: `<$> gen1 <*> gen2'
I could write this failsafe implementation:
g = flip (flip liftA2 a1) a2
but I feel that it is less readable and easier to reorganize the implementation based on functions based on infix, for example, add a different argument than the change above to use liftA3 .
You can write a chain of songs:
g = (<*> a2) . (<$> a1)
This provides a dotless style and just add arguments, but they are added to the left, not to the right of them, so you lose the correspondence with the type of function (a -> b -> c) . Also, with a lot of arguments, you get a much longer expression than just using a lambda, as in the first implementation.
So, is there a good, easy way to write the section I want, or am I stuck in lambda?