I known that r -> a is a Functor in a, and that fmap = (.) for it.
This means that when I do fmap f g, with g :: r -> a, f is applied to the result of g as soon as the latter is fed with a value of type r. However, if a is a function type, e.g. a unary function b -> c, then there's a difference between applying f to that function (which is what happens in reality) and applying f to the eventual result of g (which could be desirable in some cases; couldn't it?).
How do I map on the eventual result of g? In this case of g :: r -> b -> c it seems easy, I can just uncurry $ fmap f $ curry g. But what if also c is a function type?
Or, in other words, how do I map on the final result of multi-variable function? Is the curry/uncurry trick necessary/doable in general?
(Related question here.)
As it's apparent from comments/answers, I have not realized I was essentially asking the same question I've already asked some days ago. Probably it was not apparent to me because of how I got here. Essentially, what led me to ask this question is another one storming in my head:
If I can use liftA2 (&&), liftA2 (||), and similar to combine unary predicates, how do I combine binary predicates? To answer to this, I played around a bit in GHCi, and came up with this
liftIntoBinaryFunc p = \q r -> curry $ (liftA2 p) (uncurry q) (uncurry r)
which would allow doing something like this:
-- some binary predicate
distanceLE3 x y = 3 >= abs (x - y)
sameSign x y = ((==) `on` signum) x y
-- function to lift into binary functions
liftIntoBinaryFunc p = \q r -> curry $ (liftA2 p) (uncurry q) (uncurry r)
-- lifting && into binary functions to Bool
and' = liftIntoBinaryFunc (&&)
-- combining
pred = distance3 `and'` sameSign
-- using
p 3 18 -- False
p 3 1 -- True
p 3 (-1) -- False
However, this question too generalizes to how do I combine predicates of arbitrary (though common) arity?, and probably the answer is the same.
r -> b -> cisr -> (b -> c)and so(fmap . fmap) (f :: c -> d) (g :: r -> b -> c) :: r -> b -> d:But you will have to know how many nested levels are there, to compose the
fmapsaccordingly, or use approaches from your other recent question.