The best thing to do, when you want to infer a type for a partial application is to start from the most general types of your building blocks and search for matches between the types you're composing.
Let me make this more clear by describing you the reasoning I followed for the type you was searching for.
First of all, let's rename the type variables for (:)
in order to avoid confusion:
(.) :: (b -> c) -> (a -> b) -> a -> c
(:) :: d -> [d] -> [d]
(.) (:)
partially applies (:)
to (.)
, providing its first argument only. This means that the first argument of (.)
, that is of type (b -> c)
, is instantiated to (d -> ([d] -> [d]))
, with b == d
and c == ([d] -> [d])
(remember that ->
is right associative).
If you apply this type substitution in the whole thing, you get that the partially applied (.)
loses its first argument (it has been fixed as (:)
) and results in (a -> d) -> a -> ([d] -> [d])
, that is equivalent to (a -> d) -> a -> [d] -> [d]
(again, by right-associativity): this is the type expression you got from ghci.