How are functors in Haskell related to functors in category theory?
For as far as I understand, a functor is a mapping between two categories, for example from objects in C http://mathurl.com/32qch9w.png to objects in D http://mathurl.com/36b8r37.png where C http://mathurl.com/32qch9w.png and D http://mathurl.com/36b8r37.png are categories.
In Haskell there is Hask in which the objects are Haskell types and the morphisms are Haskell functions. However, the Functor
type class has a function fmap
which maps between these types (which are thus objects and not categories themselves):
fmap :: (a -> b) -> f a -> f b
fa
and fb
are both objects in Hask . Does this mean every instance of Functor
in Haskell is an endofunctor, and if not does Functor
really represent a functor?
What am I missing here? Are types also categories in Haskell?
An instance of Functor
specifies two things: a type constructor F
of kind * -> *
, that is, a mapping from objects of Hask to objects of Hask, and a function of type (a -> b) -> (F a -> F b)
, that is, a mapping from arrows of Hask to arrows of Hask compatible with the object-mapping F
. So, yes, all instances of Functor
are endofunctors. There are several generalizations available on Hackage, eg Control.Categorical.Functor.
Yes, all Functor
instances are endofunctors on Hask --in fact, endofunctors from all of Hask to a proper subcategory whose objects are the types obtained by applying a particular type constructor. That type constructor is what the Functor
instance is associated with, and gives the mapping for objects; the mapping for morphisms is fmap
, which (because we're only concerned with endofunctors on a cartesian closed category) is itself a family of morphisms in Hask .
It does make sense to consider other functors besides those which can have Functor
instances, such as contravariant functors (from Hask to its opposite category). The arr
function in the Arrow
class also corresponds to a functor, from all of Hask to the category whose objects are the same as those of Hask and whose morphisms are described by the type constructor the Arrow
instance is associated with.
Further generalizations are also possible (as Daniel Wagner notes), but tend to become increasingly awkward to use.
One important point about this is that what you really want is functors enriched in Hask , not just plain old functors. Hask is cartesian closed (not really, but it tries hard to be onesuch), and so it is naturally enriched in itself.
Now, enriched endofunctors give you a way of restricting to those implementable within the language: an enriched functor Hask -> Hask is a function at the level of objects (types) fa
and for each pair of objects a, b
a morphism in Hask going f : Hask (a,b) -> Hask (fa,fb). Of course, this is just fmap :: (a -> b) -> fa -> fb
上一篇: Hask的类别适合哪些值?