Composing function composition: How does (.).(.) work? - haskell

(.) takes two functions that take one value and return a value:
(.) :: (b -> c) -> (a -> b) -> a -> c
Since (.) takes two arguments, I feel like (.).(.) should be invalid, but it's perfectly fine:
(.).(.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
What is going on here? I realize this question is badly worded...all functions really just take one argument thanks to currying. Maybe a better way to say it is that the types don't match up.

Let's first play typechecker for the mechanical proof. I'll describe an intuitive way of thinking about it afterward.
I want to apply (.) to (.) and then I'll apply (.) to the result. The first application helps us to define some equivalences of variables.
((.) :: (b -> c) -> (a -> b) -> a -> c)
((.) :: (b' -> c') -> (a' -> b') -> a' -> c')
((.) :: (b'' -> c'') -> (a'' -> b'') -> a'' -> c'')
let b = (b' -> c')
c = (a' -> b') -> a' -> c'
((.) (.) :: (a -> b) -> a -> c)
((.) :: (b'' -> c'') -> (a'' -> b'') -> a'' -> c'')
Then we begin the second, but get stuck quickly...
let a = (b'' -> c'')
This is key: we want to let b = (a'' -> b'') -> a'' -> c'', but we already defined b, so instead we must try to unify --- to match up our two definitions as best we can. Fortunately, they do match
UNIFY b = (b' -> c') =:= (a'' -> b'') -> a'' -> c''
which implies
b' = a'' -> b''
c' = a'' -> c''
and with those definitions/unifications we can continue the application
((.) (.) (.) :: (b'' -> c'') -> (a' -> b') -> (a' -> c'))
then expand
((.) (.) (.) :: (b'' -> c'') -> (a' -> a'' -> b'') -> (a' -> a'' -> c''))
and clean it up
substitute b'' -> b
c'' -> c
a' -> a
a'' -> a1
(.).(.) :: (b -> c) -> (a -> a1 -> b) -> (a -> a1 -> c)
which, to be honest, is a bit of a counterintuitive result.
Here's the intuition. First take a look at fmap
fmap :: (a -> b) -> (f a -> f b)
it "lifts" a function up into a Functor. We can apply it repeatedly
fmap.fmap.fmap :: (Functor f, Functor g, Functor h)
=> (a -> b) -> (f (g (h a)) -> f (g (h b)))
allowing us to lift a function into deeper and deeper layers of Functors.
It turns out that the data type (r ->) is a Functor.
instance Functor ((->) r) where
fmap = (.)
which should look pretty familiar. This means that fmap.fmap translates to (.).(.). Thus, (.).(.) is just letting us transform the parametric type of deeper and deeper layers of the (r ->) Functor. The (r ->) Functor is actually the Reader Monad, so layered Readers is like having multiple independent kinds of global, immutable state.
Or like having multiple input arguments which aren't being affected by the fmaping. Sort of like composing a new continuation function on "just the result" of a (>1) arity function.
It's finally worth noting that if you think this stuff is interesting, it forms the core intuition behind deriving the Lenses in Control.Lens.

Let’s ignore types for a moment and just use lambda calculus.
Desugar infix notation:
(.) (.) (.)
Eta-expand:
(\ a b -> (.) a b) (\ c d -> (.) c d) (\ e f -> (.) e f)
Inline the definition of (.):
(\ a b x -> a (b x)) (\ c d y -> c (d y)) (\ e f z -> e (f z))
Substitute a:
(\ b x -> (\ c d y -> c (d y)) (b x)) (\ e f z -> e (f z))
Substitute b:
(\ x -> (\ c d y -> c (d y)) ((\ e f z -> e (f z)) x))
Substitute e:
(\ x -> (\ c d y -> c (d y)) (\ f z -> x (f z)))
Substitute c:
(\ x -> (\ d y -> (\ f z -> x (f z)) (d y)))
Substitute f:
(\ x -> (\ d y -> (\ z -> x (d y z))))
Resugar lambda notation:
\ x d y z -> x (d y z)
And if you ask GHCi, you’ll find that this has the expected type. Why? Because the function arrow is right-associative to support currying: the type (b -> c) -> (a -> b) -> a -> c really means (b -> c) -> ((a -> b) -> (a -> c)). At the same time, the type variable b can stand for any type, including a function type. See the connection?

Here is a simpler example of the same phenomenon:
id :: a -> a
id x = x
The type of id says that id should take one argument. And indeed, we can call it with one argument:
> id "hello"
"hello"
But it turns out what we can also call it with two arguments:
> id not True
False
Or even:
> id id "hello"
"hello"
What is going on? The key to understanding id not True is to first look at id not. Clearly, that's allowed, because it applies id to one argument. The type of not is Bool -> Bool, so we know that the a from id's type should be Bool -> Bool, so we know that this occurrence of id has type:
id :: (Bool -> Bool) -> (Bool -> Bool)
Or, with less parentheses:
id :: (Bool -> Bool) -> Bool -> Bool
So this occurrence of id actually takes two arguments.
The same reasoning also works for id id "hello" and (.) . (.).

This is one of those neat cases where I think it's simpler to grasp the more general case first, and then think about the specific case. So let's think about functors. We know that functors provide a way to map functions over a structure --
class Functor f where
fmap :: (a -> b) -> f a -> f b
But what if we have two layers of the functor? For example, a list of lists? In that case we can use two layers of fmap
>>> let xs = [[1,2,3], [4,5,6]]
>>> fmap (fmap (+10)) xs
[[11,12,13],[14,15,16]]
But the pattern f (g x) is exactly the same as (f . g) x so we could write
>>> (fmap . fmap) (+10) xs
[[11,12,13],[14,15,16]]
What is the type of fmap . fmap?
>>> :t fmap.fmap
:: (Functor g, Functor f) => (a -> b) -> f (g a) -> f (g b)
We see that it maps over two layers of functor, as we wanted. But now remember that (->) r is a functor (the type of functions from r, which you might prefer to read as (r ->)) and its functor instance is
instance Functor ((->) r) where
fmap f g = f . g
For a function, fmap is just function composition! When we compose two fmaps we map over two levels of the function functor. We initially have something of type (->) s ((->) r a), which is equivalent to s -> r -> a, and we end up with something of type s -> r -> b, so the type of (.).(.) must be
(.).(.) :: (a -> b) -> (s -> r -> a) -> (s -> r -> b)
which takes its first function, and uses it to transform the output of the second (two-argument) function. So for example, the function ((.).(.)) show (+) is a function of two arguments, that first adds its arguments together and then transforms the result to a String using show:
>>> ((.).(.)) show (+) 11 22
"33"
There is then a natural generalization to thinking about longer chains of fmap, for example
fmap.fmap.fmap ::
(Functor f, Functor g, Functor h) => (a -> b) -> f (g (h a)) -> f (g (h b))
which maps over three layers of functor, which is equivalent to composing with a function of three arguments:
(.).(.).(.) :: (a -> b) -> (r -> s -> t -> a) -> (r -> s -> t -> b)
for example
>>> import Data.Map
>>> ((.).(.).(.)) show insert 1 True empty
"fromList [(1,True)]"
which inserts the value True into an empty map with key 1, and then converts the output to a string with show.
These functions can be generally useful, so you sometimes see them defined as
(.:) :: (a -> b) -> (r -> s -> a) -> (r -> s -> b)
(.:) = (.).(.)
so that you can write
>>> let f = show .: (+)
>>> f 10 20
"30"
Of course, a simpler, pointful definition of (.:) can be given
(.:) :: (a -> b) -> (r -> s -> a) -> (r -> s -> b)
(f .: g) x y = f (g x y)
which may help to demystify (.).(.) somewhat.

You're right, (.) only takes two arguments. You just seem to be confused with the syntax of haskell. In the expression (.).(.), it's in fact the dot in the middle that takes the other two dots as argument, just like in the expression 100 + 200, which can be written as (+) 100 200.
(.).(.) === (number the dots)
(1.)2.(3.) === (rewrite using just syntax rules)
(2.)(1.)(3.) === (unnumber and put spaces)
(.) (.) (.) ===
And it should be even more clear from (.) (.) (.) that the first (.) is taking the second (.) and third (.) as it's arguments.

Yes this is due to currying. (.) as all functions in Haskell only takes one argument. What you are composing is the first partial call to each respective composed (.) which takes its first argument (the first function of the composition).

(Read my answer on function composition, $ operator and point-free style first.)
Imagine you have a simple function: it adds up 2 numbers and then negates the result. We'll call it foo:
foo a b = negate (a + b)
Now let's make it point-free step by step and see what we end up with:
foo a b = negate $ a + b
foo a b = negate $ (+) a b
foo a b = negate $ (+) a $ b
foo a b = negate . (+) a $ b
foo a = negate . (+) a -- f x = g x is equivalent to f = g
foo a = (.) negate ((+) a) -- any infix operator is just a function
foo a = (negate.) ((+) a) -- (2+) is the same as ((+) 2)
foo a = (negate.) $ (+) a
foo a = (negate.) . (+) $ a
foo = (negate.) . (+)
foo = ((.) negate) . (+)
foo = (.) ((.) negate) (+) -- move dot in the middle in prefix position
foo = ((.) ((.) negate)) (+) -- add extra parentheses
Now let's analyze expression (.) ((.) negate) more closely. It's a partial application of (.) function, whose first argument is ((.) negate). Can we transform it even further? Yes we can:
(.) ((.) negate)
(.) . (.) $ negate -- because f (f x) is the same as (f . f) x
(.)(.)(.) $ negate
((.)(.)(.)) negate
(.).(.) is equivalent to (.)(.)(.), because in the 1st expression, the dot in the middle can be moved in prefix position and surrounded with parentheses, which gives rise to the 2nd expression.
Now we can rewrite our foo function:
foo = ((.).(.)) negate (+)
foo = ((.)(.)(.)) negate (+) -- same as previous one
foo = negate .: (+)
where (.:) = (.).(.)
Now you know that (.).(.) is equivalent to (\f g x y -> f (g x y)):
(\f g x y -> f (g x y)) negate (+) 2 3 -- returns -5
((.).(.)) negate (+) 2 3 -- returns -5

Related

Shouldn't fmap (+3) (*3) be equivalent to \x -> ((x+3)*3)?

In Learn you a Haskell, it is given that
fmap (+3) (*3)
is equivalent to
\x -> ((x*3)+3))
However, I can't understand why. Isn't it supposed to be \x -> ((x+3)*3)?
I don't know the implementation of fmap for (*3) functor, but my intuition tells me that since the functor (*3) is equivalent to \x -> x * 3, the map (+3) would be first applied and then (*3) be applied, but it is the other way around. What am I missing in here?
my intuition tells me that since the functor (*3) is equivalent to \x -> x * 3
Functions form a functor instance
instance Functor ((->) r) where ...
Those are the functions mapping from r.
Given a function g :: r -> a you can form a new function h :: r -> b with the help of f :: a -> b via h = fmap f g. It should now be clear that f :: a -> b cannot be applied first but must be applied second. That is h' = (g :: r -> a) . (f :: a -> b) does not make any sense but h = (f :: a -> b) . (g :: r -> a) does.
fmap has to obey two laws:
fmap id == id
fmap (f . g) == fmap f . fmap g
Your proposed definition, fmap' f g == g . f, satisfies the first law but violates the second law:
fmap' id f == f . id == f == id f -- OK
fmap' (f . g) h == h . (f . g)
== (h . f) . g
== (fmap' f h) . g
== fmap' g (fmap' f h)
== (fmap' g . fmap' f) h -- violation, since (.) is not commutative
The correct definition, fmap f g = f . h, satisfies both:
fmap id f == id . f == f == id f
fmap (f . g) h == (f . g) . h
== f . (g . h)
== fmap f (g . h)
== fmap f (fmap g h)
== (fmap f . fmap g) h
A "functor", in Haskell, is a higher order type, F, -- "higher order" meaning, it accepts another type variable, a (denoting any type whatever), -- such that we can have
F a fa
(a -> b) ab
-----------------
F b fmap ab fa
which is known as "flip fmap" (flip just means that the order of arguments is flipped, flip fmap fa ab == fmap ab fa). There are also some "common sense" laws it must follow.
For F ~ Maybe, say, it means
flip fmap :: Maybe a ->
(a -> b) ->
Maybe b
and for F ~ [],
flip fmap :: [] a ->
(a -> b) ->
[] b
which is more conventionally written as [a] -> (a -> b) -> [b].
In our case here, F a ~ r -> a, or more formally, F a ~ ((->) r) a, which means F ~ ((->) r),
flip fmap :: ((->) r) a ->
(a -> b) ->
((->) r) b
which is more conventionally written as (r -> a) -> (a -> b) -> (r -> b),
r -> a
a -> b
-------------
r -> b
which is the same as (r -> a) -> (a -> b) -> r -> b since with types, the arrows associate on the right, corresponding to the fact that applications associate on the left: f a b c is actually ((f a) b) c and
f a b c = d -- f a b c
f a b = \c -> d -- (f a b) c
f a = \b c -> d -- ((f a) b) c
f = \a b c -> d -- (((f) a) b) c
are all different ways to write down the same definition, and different ways to write down the same function call.
This then means we need to implement
fmap :: (a -> b) -> (r -> a) -> (r -> b)
fmap ab ra r = b
where
b =
So what could the definition be? Is it up to us to decode what goes where? Well, we must produce a b type value. The only thing we have that can do it for us, is ab :: a -> b.
Can we produce a b without it? Out of the blue? Except for erroring out, no, we can't -- we know nothing about that b type. It can be anything. So we're left with
b = ab a
a =
and now we must get an a somewhere, to use it as an argument to ab. Fortunately, ra can give it to us:
a = ra r
and r, we already got! So the types did write this implementation for us:
fmap :: (a -> b) -> (r -> a) -> (r -> b)
fmap ab ra r = b
where
b = ab a
a = ra r
or, simplifying and renaming, we get
fmap f g r = f ( g r)
= (f . g) r
by definition of the function composition, ., as
(.) :: (a -> b) -> (r -> a) -> (r -> b)
(f . g) r = f (g r)
which is a valid syntax definition, otherwise written as
(.) :: (a -> b) -> (r -> a) -> (r -> b)
(.) f g r = f (g r)
or
(.) :: (a -> b) -> (r -> a) -> (r -> b)
(.) f g = \ r -> f (g r)
or
(.) :: (a -> b) -> (r -> a) -> (r -> b)
(.) = \f g r -> f (g r)
All these are equivalent. And its type diagram
a -> b
r -> a
--------------
r -> b
As for the intuition, a functorial type value of type F A is, loosely, an F-type "something" than can somehow produce an A-type something, in some F-type sense.
The functor laws mean that F does so in some purely "structural", mechanical way, without regard to what that A value that it produces actually is. In other words, the A values do not influence how they are produced, only the F type itself determines that.
For example, Maybe Int could Maybe produce an Int. Or [Int] could produce several Ints. (*3) can also produce an Int, if we supply it with an Int argument.
What then this fmap is? What does it do? It transforms that would-be produced value. Every functor type must define its fmap, that is what makes it be a functorial type, that it defines the
instance Functor Maybe where
fmap ab (Just a) = (Just (ab a))
etc. So then, with functions r -> a, which produce that a type value promised by their type, after being applied to an argument, we transform that value by applying the transformation function to it:
fmap transf mult3 arg = tansf (mult3 arg)
which is just the definition of the functional composition itself, with arguments renamed.
So that's why, in this case,
fmap (+3) (*3) r = (+3) ((*3) r)
= (+3) (r*3)
= (r*3) + 3
we (+3) transform the value produced by (*3) in the ((->) r) sense, which is application to some user-supplied argument, r. So (*3) must be applied first, to get (it to produce) that value.

Understanding the signature of the function (.) (:)

could you explain how we go from :
Prelude Data.Monoid> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
Prelude Data.Monoid> :t (:)
(:) :: a -> [a] -> [a]
to that :
Prelude Data.Monoid> :t (.)(:)
(.)(:) :: (a1 -> a2) -> a1 -> [a2] -> [a2]
More in general, I'm sometimes afraid of (.) like I don't feel it intuitively, if you have some tricks to share to better feel it, it's welcome :-)
First, let's rename some things and put parenthesis:
(:) :: d -> ([d] -> [d])
Now, in the expresstion (.) (:) the (:) is the first argument of (.). The first argument of (.) should have type b -> c. Thus,
b -> c = d -> ([d] -> [d])
which means
b = d
c = [d] -> [d]
The result of (.) (:) has type (a -> b) -> a -> c. Putting our b and c in, we get
(a -> d) -> a -> ([d] -> [d])
This is exactly what ghci told you, except for the type variables renamed as a1 = a and a2 = d.
Well, let us do the type inference. We thus have two function:
(.) :: (b -> c) -> (a -> b) -> a -> c
(:) :: d -> [d] -> [d]
We here use d since the a in (.) is not per se the a in (:), so we avoid confusion by using two separate type variables.
The type signatures in a more canonic form are:
(.) :: (b -> c) -> ((a -> b) -> (a -> c))
(:) :: d -> ([d] -> [d])
So now since (:) is the argument of a function application with (.) as function, we know that the type of (:) is the type of the parameter of (.), so that means that d -> ([d] -> [d]) ~ (b -> c) (here the tilde ~ means that it is the same type). So therefore we know that:
b -> c
~ d -> ([d] -> [d])
---------------------
b ~ d, c ~ [d] -> [d]
So that means that the b in the type signature of (.) is the same type as d in the type signature of (:), and that c ~ [d] -> [d].
So the as a result, we get:
(.) (:) :: (a -> b) -> (a -> c))
= (.) (:) :: (a -> d) -> (a -> ([d] -> [d])))
= (.) (:) :: (a -> d) -> (a -> [d] -> [d])
= (.) (:) :: (a -> d) -> a -> [d] -> [d]
Writing (.) (:) as an operator section, ((:) .), emphasises a bit that it postcomposes (:) with some other function (i.e. it modifies a function by applying (:) to its result -- \g -> (g .) is fmap for functions). Symmetrically, (. (:)) precomposes (:) with some other function (\f -> (. f) is contramap for functions -- cf. the Op newtype).
(.) is nothing to fear. It is a most natural thing.
Imagine you define an abstract class of "connections":
class Connecting conn where
plug :: conn a b -> conn b c -> conn a c
noop :: conn a a
conn a b is a type of something which is connecting a point a to a point b. Given the possibility of connecting a to b, and b to c, it most naturally gives us the possibility of connecting a to c by just plugging the two somethings together. Also, any point which can be connected to another, and can get connected to, can obviously be considered connected to itself with absolutely no effort.
Functions are connecting. Just use the output of one as the input of another. If we have such two compatible functions, plugging them in that way gives us a combined connection.
Functions are Connecting:
instance Connecting (->) where
-- plug :: (->) a b -> (->) b c -> (->) a c
(plug f g) x = g (f x)
-- noop :: (->) a a
noop x = x -- what else? seriously. All we have is x.
Interesting thing about that plug :: (->) a b -> (->) b c -> (->) a c. That order of arguments is most fitting when we think about the types involved. But looking at its definition, we'd prefer it be defined as
gulp :: (->) b c -> (->) a b -> (->) a c
(gulp g f) x = g (f x)
Now the definition makes most sense, but the type feels a bit tortured.
Never mind that, we can have both:
(f :: a -> b) >>> (g :: b -> c) :: -- ...
a -> c
(g :: b -> c) <<< (f :: a -> b) :: -- ...
a ->
c
Coincidentally, <<< is also known as (.).
It is also clear that we have (.) = (<<<) = flip (>>>), so (g . f) x = g (f x) = (f >>> g) x.
Presented with g . f, it is often easier to deal with the equivalent expression f >>> g, types-wise. Just align the types, vertically,
(:) :: b -> ([b] -> [b])
f :: a -> b
f >>> (:) :: a -> ([b] -> [b])
so that
(>>> (:)) :: (a -> b) -- = ((:) <<<) = ((:) .) = (.) (:)
-> a -> ([b] -> [b])
because (>>> (:)) = (\f -> (f >>> (:))).
Which is (\f -> ((:) <<< f)) = (\f -> ((:) . f)) = ((:) .) = (.) (:).
edit: for instance, the type of (Endo . (:)) = ((:) >>> Endo) is easily arrived at, with:
Endo :: ( b -> b ) -> Endo b
(:) :: a -> ([a] -> [a]) -- b ~ [a]
(:) >>> Endo :: a -> Endo [a]
For more about Endo, try both :t Endo and :i Endo at GHCi prompt, and read up on Haskell's record syntax, if you need to.

Parenthesis around operator symbol in type signature

. :: (a -> b) -> (c -> a) -> c -> b
f . g = \ x -> f (g x)
Why is this definition illegal? Aesthetic choice, or formal necessity?
It's for consistency. Infix operators by themselves aren't expressions whose type or value you could define. The following is also not legal:
. = \f g x -> f (g x)
...though that is basically what your definition is desugared to. But for directly defining the value of an infix this way, we need to first disable the special syntactic status, and that's done by wrapping it in parentheses:
(.) :: (a -> b) -> (c -> a) -> c -> b
(.) = \f g x -> f (g x)
This is quite the same as defining
compose :: (a -> b) -> (c -> a) -> c -> b
compose = \f g x -> f (g x)
...which can then also be used as an infix, like
Prelude> map (toEnum `compose` round) $ [110 + sin x * 12 | x<-[0..30]] :: String
"nxypebkvzsgbhszvkbepyxndclwyqfb"
But you obviously wouldn't write the definition in infix form, like
`compose` :: (a -> b) -> (c -> a) -> c -> b
`compose` = \f g x -> f (g x)
...though you could do
f`compose`g = \x -> f (g x)

Applying compose to fmap

For weeks I've been trying to figure out how the Haskell compiler applies the (.) to fmap.
What I mean is.
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
:t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
:t (.) fmap
(.) fmap :: Functor f => (a -> a1 -> b) -> a -> f a1 -> f b
How did the compiler arrive at the type for (.) fmap?
I was actually going to ask this question here but while I was explaining what I've tried it all came together. So now I'm just going to post the answer too.
To get this I took fmap
fmap :: Functor f => (a -> b) -> f a -> f b
fmap :: Functor f => (a -> b) -> (f a -> f b)
if
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
then
(b -> c) of the start of the (.) function can be replaced with
((a -> b) -> (f a -> f b))
thus I have
((a1 -> b) -> (f a1 -> f b)) -> (a -> (a1 -> b)) -> a -> (f a1 -> f b)
Since (.) has been applied to fmap, we can eliminate ((a1 -> b) -> (f a1 -> f b)) and we are left with
(a -> (a1 -> b)) -> a -> (f a1 -> f b)
Then to be extra clean we can eliminate extra parentheses.
Glguy and Hamme from the IRC Beginner-haskell channel both reminded me (->) is right associative
e.g. (a -> b -> c -> d) = (a -> (b -> (c -> d)))
so we eliminate the redundant parentheses.
(a -> a1 -> b) -> a -> f a1 -> f b
:t (.) fmap
(.) fmap :: Functor f => (a -> a1 -> b) -> a -> f a1 -> f b
The type signature can be understood intuitively if you rename a to c, rename a1 to a, and add an extra pair of parentheses:
> :t (.) fmap
(.) fmap :: Functor f => (c -> (a -> b)) -> c -> f a -> f b
The first argument is a function that returns another function (a -> b) that gets fed into fmap. Applying the first argument produces the fully composed function waiting on that one argument c. Applying c produces fmap (a -> b) which is only waiting on the last argument f a.
((.) fmap)
((.) fmap (c -> (a -> b)) -- Apply the 1st argument
((.) fmap (c -> (a -> b)) c -- Apply the 2nd argument
fmap (a -> b)
fmap (a -> b) f a -- Apply the 3rd argument
f b -- The result
An example:
> ((.) fmap) (\n -> (+n)) 42 [1..5] -- Becomes: fmap (+42) [1..5]
[43,44,45,46,47]
> ((.) fmap) (\n -> (+n)) 13 [1..5]
[14,15,16,17,18]
One way to understand how the type is derived is to look at what (fmap .) means.
Consider fmap . g: what does this mean? Expanding the definition of ., we see that fmap . g = \x -> fmap (g x). Since the first argument to fmap needs to be a function with type a -> b, g must be function with a type like c -> a -> b; it computes an appropriate function given an argument.
Now, whereas we can apply fmap f directly to a list (or other functor), we need to give fmap . g an argument first:
fmap f someFunctorialValue == someOtherFunctorialValue
((fmap . g) x) someFunctorialValue == someOtherFunctorialValue
Dropping some redundant parentheses, this becomes
(fmap .) g x someFunctorialValue == someOtherFunctorialValue
and now we can directly what the type of each expression should be:
-- someFunctorialValue :: Functor f => f a
-- someOtherFunctorialValue :: Functor f => f b
-- x :: c
-- g :: (c -> a -> b)
-- (fmap .) :: (c -> a -> b) -> c -> f a -> f b
-- fmap :: ( a -> b) -> f a -> f b
In other words: fmap takes a concrete function a -> b, while (fmap .) takes a "parameterized" function g and a "function selector" x.

Defining f(x,y) = (x + y) % 3 in Haskell [duplicate]

Ordinary function composition is of the type
(.) :: (b -> c) -> (a -> b) -> a -> c
I figure this should generalize to types like:
(.) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
A concrete example: calculating difference-squared. We could write diffsq a b = (a - b) ^ 2, but it feels like I should be able to compose the (-) and (^2) to write something like diffsq = (^2) . (-).
I can't, of course. One thing I can do is use a tuple instead of two arguments to (-), by transforming it with uncurry, but this isn't the same.
Is it possible to do what I want? If not, what am I misunderstanding that makes me think it should be possible?
Note: This has effectively already been asked here, but the answer (that I suspect must exist) was not given.
My preferred implementation for this is
fmap . fmap :: (Functor f, Functor f1) => (a -> b) -> f (f1 a) -> f (f1 b)
If only because it is fairly easy to remember.
When instantiating f and f1 to (->) c and (->) d respectively you get the type
(a -> b) -> (c -> d -> a) -> c -> d -> b
which is the type of
(.) . (.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
but it is a bit easier to rattle off the fmap . fmap version and it generalizes to other functors.
Sometimes this is written fmap fmap fmap, but written as fmap . fmap it can be more readily expanded to allow more arguments.
fmap . fmap . fmap
:: (Functor f, Functor g, Functor h) => (a -> b) -> f (g (h a)) -> f (g (h b))
fmap . fmap . fmap . fmap
:: (Functor f, Functor g, Functor h, Functor i) => (a -> b) -> f (g (h (i a))) -> f (g (h (i b))
etc.
In general fmap composed with itself n times can be used to fmap n levels deep!
And since functions form a Functor, this provides plumbing for n arguments.
For more information, see Conal Elliott's Semantic Editor Combinators.
The misunderstanding is that you think of a function of type a -> b -> c as a function of two arguments with return type c, whereas it is in fact a function of one argument with return type b -> c because the function type associates to the right (i.e. it's the same as a -> (b -> c). This makes it impossible to use the standard function composition operator.
To see why, try applying the (.) operator which is of type (y -> z) -> (x -> y) -> (x -> z) operator to two functions, g :: c -> d and f :: a -> (b -> c). This means that we must unify y with c and also with b -> c. This doesn't make much sense. How can y be both c and a function returning c? That would have to be an infinite type. So this does not work.
Just because we can't use the standard composition operator, it doesn't stop us from defining our own.
compose2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d
compose2 g f x y = g (f x y)
diffsq = (^2) `compose2` (-)
Usually it is better to avoid using point-free style in this case and just go with
diffsq a b = (a-b)^2
I don't know of a standard library function that does this, but the point-free pattern that accomplishes it is to compose the composition function:
(.) . (.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
I was going to write this in a comment, but it's a little long, and it draws from both mightybyte and hammar.
I suggest we standardize around operators such as .* for compose2 and .** for compose3. Using mightybyte's definition:
(.*) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.*) = (.) . (.)
(.**) :: (d -> e) -> (a -> b -> c -> d) -> (a -> b -> c -> e)
(.**) = (.) . (.*)
diffsq :: (Num a) => a -> a -> a
diffsq = (^2) .* (-)
modminus :: (Integral a) => a -> a -> a -> a
modminus n = (`mod` n) .* (-)
diffsqmod :: (Integral a) => a -> a -> a -> a
diffsqmod = (^2) .** modminus
Yes, modminus and diffsqmod are very random and worthless functions, but they were quick and show the point. Notice how eerily easy it is to define the next level by composing in another compose function (similar to the chaining fmaps mentioned by Edward).
(.***) = (.) . (.**)
On a practical note, from compose12 upwards it is shorter to write the function name rather than the operator
f .*********** g
f `compose12` g
Though counting asterisks is tiring so we may want to stop the convention at 4 or 5 .
[edit] Another random idea, we could use .: for compose2, .:. for compose3, .:: for compose4, .::. for compose5, .::: for compose6, letting the number of dots (after the initial one) visually mark how many arguments to drill down. I think I like the stars better though.
As Max pointed out in a comment:
diffsq = ((^ 2) .) . (-)
You can think of f . g as applying one argument to g, then passing the result to f. (f .) . g applies two arguments to g, then passes the result to f. ((f .) .) . g applies three arguments to g, and so on.
\f g -> (f .) . g :: (c -> d) -> (a -> b -> c) -> a -> b -> d
If we left-section the composition operator with some function f :: c -> d (partial application with f on the left), we get:
(f .) :: (b -> c) -> b -> d
So we have this new function which expects a function from b -> c, but our g is a -> b -> c, or equivalently, a -> (b -> c). We need to apply an a before we can get what we need. Well, let's iterate once more:
((f .) .) :: (a -> b -> c) -> a -> b -> d
Here's what I think is an elegant way to achieve what you want. The Functor type class gives a way to 'push' a function down into a container so you can apply it to each element using fmap. You can think of a function a -> b as a container of bs with each element indexed by an element of a. So it's natural to make this instance:
instance Functor ((->) a) where
fmap f g = f . g
(I think you can get that by importing a suitable library but I can't remember which.)
Now the usual composition of f with g is trivially an fmap:
o1 :: (c -> d) -> (b -> c) -> (b -> d)
f `o1` g = fmap f g
A function of type a -> b -> c is a container of containers of elements of type c. So we just need to push our function f down twice. Here you go:
o2 :: (c -> d) -> (a -> (b -> c)) -> a -> (b -> d)
f `o2` g = fmap (fmap f) g
In practice you might find you don't need o1 or o2, just fmap. And if you can find the library whose location I've forgotten, you may find you can just use fmap without writ
ing any additional code.

Resources