g . f
means applying f
first, then applying g
to the result of f
, in
other words, it can be rewritten as
\x -> g (f x)
Therefore,
((+) . (+))
can be rewritten as
\x -> (\y -> (x +) + y)
According to the type of (+)
, in the above lambda abstraction, x
needs
having type Num a => a
, y
having type Num a => Num (a -> a)
, as inferred
by ghci
(Num a, Num (a -> a)) => a -> (a -> a) -> a -> a
So if we have made a -> a
an instance of type class Num a
, for example,
here is one way to achieve that
{-# LANGUAGE FlexibleInstances #-}
instance (Num a) => Num ((->) a a) where
a + b = \x -> a x + b x
a * b = \x -> a x * b x
a - b = \x -> a x - b x
negate a = \x -> negate $ a x
abs a = \x -> abs $ a x
signum a = \x -> signum $ a x
fromInteger n = \_x -> fromInteger n
we can use ((+) . (+))
like this
*Main> ((+) . (+)) 1 (+2) 3
9
Because ((+) . (+))
equals
\x -> \y -> (x +) + y
which means ((+) . (+)) 1 (+2) 3
equals
((1 + ) + (+ 2)) 3
according to the definition of (+)
in the instance of (a -> a)
, ((1+) +
(+2))
equals
\x -> (1+x) + (x+2)
So ((1+) + (+2)) 3
equals (1+3) + (3+2)
, which is 9, as given by ghci
.
map . map
is similar, as indicated by its type, given by ghci
:
(a -> b) -> [[a]] -> [[b]]
the first argument of that function should be a function of type a->b
, the
second argument should be a nested list of type [[a]]
, and that composed
function map . map
will apply the first argument to each element of each
list in its second argument, return a nested list of type [[b]]
. For
example
*Main> (map . map) (+1) [[1,2], [3,4,5]]
[[2,3],[4,5,6]]