From categorical point of view, functor is pair of two maps (one between objects and another between arrows of categories), following some axioms.
I have assumed, what every Functor instance is similar to mathematical definition i.e. can map both objects and functions, but Haskell's Functor
class has only function fmap
which maps functions.
Why so?
UPD In other words:
Every Monad type M
has an function return :: a -> M a
.
And Functor type F
has no function return :: a -> F a
, but only F x
constructor.
Though you were using those fancy categorical terms in your question and should be completely satisfied with the existing answers, here is an attempt for a rather trivial explanation:
Suppose there would be a function
return
(orpure
orunit
or...
) in the Functor type class.Now try to define some common instances of Functor:
[]
(Lists),Maybe
,((,) a)
(Tuples with a left component)Easy enough, eh?
Here are the ordinary Functor instances:
What about
return
for Functor now?Lists:
Alright. What about Maybe?
Okay. Now Tuples:
You see, it is unknown which value should be filled into the left component of that tuple. The instance declaration says it has a type
a
but we do not know a value from that type. Maybe the type a is theUnit
type with only one value. But if itsBool
, should we takeTrue
orFalse
? If it isEither Int Bool
should we takeLeft 0
orRight False
orLeft 1
?So you see, if you had a
return
on Functors, you could not define a lot of valid functor instances in general (You would need to impose a constraint of something like a FunctorEmpty type class).If you look at the documentation for
Functor
andMonad
you will see that there are indeed instances forFunctor ((,) a)
but not forMonad ((,) a)
. This is because you just can't definereturn
for that thing.First of all, there are two levels: types and values. As objects of Hask are types, you can map them only with type constructors, which have the
* -> *
kind:α -> F α
(forFunctor F
),β -> M β
(forMonad M
).Then for a functor you need a map on morphisms (i.e. functions, which are values): it's just
fmap :: (α -> β) -> (F α -> F β)
.So far, I guess, I'm not saying anything new. But important thing is that
return :: α -> M α
ofMonad
is not a mapper of a typeα
to theM α
as you may think. Regarding to the math definition of a monad,return
corresponds to a natural transformation fromId
functor to theM
functor. Just that thisId
functor is kind of implicit. The standard definition of monad requires also another natural transformationM ◦ M -> M
. So translating it to Haskell would be like(As a side-note: these two natural transformations are actually the unit and multiplication, which make monad a monoid in the category of endofunctors)
The actual definition differs but is equivalent. See Haskell/wiki on that.
If you take the composition-like operator derived form the standard bind
>>= :: m α -> (α -> m β) -> m β
:you can see, that it's all actually about the Kleisli category. See also the article on nLab about monads in computer science.
If you have
Then the type constructor
F
is the action on objects (which are types) taking a typeT
to the typeF T
, andfmap
is the action on morphisms (which are functions) taking a functionf :: T -> U
tofmap f :: F T -> F U
.Objects of a category are not the same as objects in a OO programming language (we prefer to call those values in Haskell; what they mean in category theory was discussed here). Rather, the objects of Hask are types. Haskell
Functor
s are endofunctors in Hask, i.e. associate types to types, by the following means:OTOH, the arrows of Hask are in fact values, of some function type
a -> b
. These are associated in the following way: