(.)
takes two functions that take one value and return a value:
(.) :: (b -> c) -> (a -> b) -> a -> c
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 (.) . (.)
.