In Category Theory, a Functor is a morphism between categories, that is, it maps each object in category A
to another object in B
, as well as mapping each morphism C -> D
onto the respective objects in B
, while preserving composition of morphisms. So one could say a functor is composed of two "parts", one that maps Objects to Objects, and one that maps Morphisms to Morphisms.
In Haskell if I understood it properly, each Type in The Functor
typeclass can be "mapped onto", that is a function of Type a -> b
can be mapped onto a function F a -> F b
. Now why doesn't there exist a return :: Functor f => a -> f a
function, specifically for Functor
? Is there no need, since we can simply utilize the definition of return
in the Monad
instance, since return is really only working on the functor part of a Monad, or is there another reason?
It striked me as strange, because if that were the way, why would't return
be included in the Functor
instance? I mean every monad has a functor part, so to me, that would make sense. Can anyone enlighten me in that matter?
CodePudding user response:
That's a common misconception and one that used to trip me up. You're right that a functor has two parts: one that maps objects to objects and one that maps functions to functions (more generally, arrows to arrows, but that's not really germane here). Now, when I have
instance Functor F where
fmap f x = ...
You've already correctly surmised that fmap
takes functions to functions. However, we already have a way to take objects to objects. Categorically, our objects are not values, they're types. So the "objects to objects" part is something that should map a type to another type. And that thing is called F
. The name of our functor literally is the mapping from objects to objects. Given a type a
, the type F a
is some other type lifted by our functor.
Now that raises the fair question: What is return
? It takes an a
and produces an F a
(for a monad F
). More specifically, given a fixed monad F
, the signature is
return :: forall a. a -> F a
Now carefully read that. That says "given any type a
, I can come up with a function from a
to F a
". That is, it takes an object in our category (a type) and maps it into an arrow in our category (a function). A mapping from an object to an arrow is called a natural transformation, and that's exactly what return
is.
Categorically speaking, a monad is a functor (the underlying type F
together with fmap
), together with two natural transformations:
return
, which is a natural transformation1 -> F
(where1
is the identity functor), andjoin
, which is a natural transformationF^2 -> F
(whereF^2
isF
composed with itself)
That is, for any type a
, return
has type a -> F a
and join
has type F (F a) -> F a
[1].
What would a typeclass with return
and fmap
look like? I'm not sure. I don't know of a Haskell library that implements that typeclass, and I'm not entirely sure what the laws would look like. A good guess might be fmap f . return === return . f
, but we actually get that as a free theorem, so that's not our law. If you or someone else knows of this typeclass somewhere in the Hackage ecosystem, feel free to let me know.
[1] Haskell uses an equivalent definition of "monad" in terms of the bind operator (>>=)
rather than join
. They're equivalent mathematically, and I opted for the simpler definition here.