Let's look at each line separately.
class Functor f where
This declares a single-parameter type class called Functor
; the type which satisfies it will be called f
.
fmap :: (a -> b) -> f a -> f b
Like any function definition, all the free type variables are implicitly forall
ed—they can be replaced with anything. However, thanks to the first line, f
is in scope. Thus, fmap
has the type signature fmap :: forall a b. Functor f => (a -> b) -> f a -> f b
. In other words, every functor needs to have a definition of fmap
which can work for any a
and b
, and f
must have kind (the type of a type) * -> *
; that is, it must be a type which takes another type, such as []
or Maybe
or IO
.
What you said, then, is incorrect; the a
isn't special, and if we had another function in Functor
, it wouldn't see the same a
or b
. However, the compiler does use the f a
bit to figure out what the kind of f
must be. Additionally, your Foo
class is perfectly legal; I could specify an instance as follows
instance Foo (a -> b) where
foo f _ = f
This satisfies foo :: a -> b -> a
for any b
; note that the b
in Foo (a -> b)
is different. Admittedly, it's not a very interesting instance, but it's perfectly legal.