Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly are the categories that are being mapped by Applicative Functors?

Tags:

I've been reading up on Applicative Functors and I am having difficulty reconciling a mismatch in the respective terminologies of category theory and functional programming.

Although I have looked over various blogs, the most complete resources that I have been using for this research are:

  • McBride & Paterson - Applicative Programming with effects (PDF)
  • Gibbons & Oliveira - The Essence of the Iterator Pattern (PDF)
  • Tomas Petricek - Writing idioms in LINQ

In category theory, a functor is a morphism from a source category to a target category (in a category of categories). The "category of categories" has a collection of objects that contains both the source and target categories and a collection of functors that contains: the source category's identity functor; the target category's identity functor; and, the functor connecting the source to the target (If the source category is the same as the target category and the functor in question is the identity, then there need only be that one functor).

In functional programming, applicative functors are described as a pair of operations:

  • pure : a -> f a
  • <*> : f ( a -> b) -> f a -> f b.

Here's my question

What interpretation makes clear the correspondence between the the functional programming definition of an applicative functor and the category theoretical definition of a functor?

More specifically, what parts of the tuple (pure,<*>) correspond to:

  1. the source category
  2. the target category
  3. the category where the functor lives
  4. the functor's structure-preserving effect on the objects of the source category
  5. the functor's structure-preserving effect on the morphisms of the source category

Notes: I recognize that this may be an incomplete metaphor, and there may not be a one-to-one correspondence for each of the concepts that I mentioned. I have purposely refrained from sharing my speculation about the apparent correspondences here in order to keep my question simple and to avoid confounding the issues further.

like image 266
smartcaveman Avatar asked Jun 29 '13 02:06

smartcaveman


People also ask

What is the category of functors?

Functors are the structure-preserving maps of categories; they can be composed, so there is a (large) category Cat consisting of small categories and functors. Informally, there is also a (huge) category CAT consisting of all categories and functors.

What are functors in Haskell?

Functor in Haskell is a kind of functional representation of different Types which can be mapped over. It is a high level concept of implementing polymorphism. According to Haskell developers, all the Types such as List, Map, Tree, etc. are the instance of the Haskell Functor.

What are functors in functional programming?

In functional programming, a functor is a design pattern inspired by the definition from category theory, that allows for a generic type to apply a function inside without changing the structure of the generic type. This idea is encoded in Haskell using type class.

What is functor category theory?

A Functor is kind of mapping of objects and morphisms that preserves composition and identity. We have two Categories: A and B . In Category A we have two objects a and b with morphism f . Our Functor is a mapping of objects a and b to Fa and Fb and mapping of morphisms, in this case single morphism: f to Ff .


2 Answers

Paraphrasing this answer: Applicative functors are functors for which there is also a natural transformation that preserve monoidal structure of their source/target categories. In the case of Haskell's Applicative endofunctors (because their source and target categories is Hask), the monoidal structure is the Cartesian product. So for an Applicative functor there are natural transformations φ: (f a, f b) -> f (a, b) and ι: () -> f (). So we could define Applicative as

class Functor f => Applicative' f where     φ :: (f a, f b) -> f (a, b)     ι :: f ()       -- it could be \() -> f (),                     -- but \() -> ... is redundant 

This definition is equivalent to the standard one. We can express

φ = uncurry (liftA2 (,))   = \(x, y) -> (,) <$> x <*> y  ι = pure () 

and conversely

pure x   = fmap (\() -> x) ι  f <*> x  = fmap (uncurry ($)) (φ (f, x)) 

So pure and <*> is an alternative way how to define this natural transformation.

like image 143
Petr Avatar answered Nov 16 '22 22:11

Petr


It's probably simpler to look at the class Functor first (which is a superclass of Applicative). Applicative corresponds to a "lax monoidal functor", as the first paper you linked to points out. The definition of Functor is:

class Functor f where   fmap :: (a -> b) -> f a -> f b 

An instance of Functor is a type constructor (of kind * -> *). An example is Maybe.

The category we're talking about is the category "Hask" that has Haskell types as objects and (monomorphic) Haskell functions as morphisms. Every instance of Functor (and Applicative, Monad, etc.) is an endofunctor in this category, i.e. a functor from the category to itself.

The two maps of the functor -- Haskell-types-to-Haskell-types and Haskell-functions-Haskell-functions -- are the type constructor f and the function fmap.

For example, Int and Maybe Int are both objects in Hask; Maybe maps from the former to the latter. If chr :: Int -> Char, then fmap maps it to fmap chr :: Maybe Int -> Maybe Char. The Functor laws correspond to the categorical functor laws.

In the case of Applicative, Functor is a superclass, so everything I just said applies. In this particular case you can implement fmap using pure and <*> -- liftA f x = pure f <*> x -- so the two parts of the functor that you were looking for are f and liftA. (But note that other formulations of Applicative don't let you do that -- in general you would rely on the Functor superclass.)

I'm not quite sure what you mean here by "the category where the functor lives".

like image 45
shachaf Avatar answered Nov 16 '22 22:11

shachaf