# Wait, how does that even typecheck ``` (.) :: (b -> c) -> (a -> b) -> a -> c -- fmap fmap fmap :: Functor f => (m -> n) -> f m -> f n fmap :: Functor g => (x -> y) -> g x -> g y ``` Let's typecheck `fmap . fmap.`. 1. First, it's important to note that `fmap` is a function that takes a function `m -> n` and returns a function `f m -> f n`. 2. Using that information we see that `a` is actually `m -> n`. 3. We also see that `b` is actually `f m -> f n` **and** `x -> y`, so `x` has to be `f m` and `y` has to be `f n`. 4. We can then also conclude that `g x` is `g (f m)` and `g y` is `g (f n)` Armed with this knowledge, we can apply fmap to (.) a first time `(fmap.) :: (Functor g) => (a -> (f m -> f n)) -> a -> g (f m) -> g (f n)` And now we apply it a second time: `(fmap . fmap) :: (Functor g, Functor f) => (m -> n) -> g (f m) -> g (f n)`