21

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.

laughedelic
  • 6,230
  • 1
  • 32
  • 41
uhbif19
  • 3,139
  • 3
  • 26
  • 48
  • 2
    What do you mean by "situation is completly opposite for `Functor` and for `Monad` classes"? Since monads _are_ functors, it can't be opposite. — As for "why category theory argument is applicable to Haskell type theory": type theory has nothing to do with this whatsoever. It's just the _Haskell standard libraries_, they implement type classes which are _modelled after category theory concepts_. – leftaroundabout Mar 03 '14 at 16:24
  • @leftaroundabout Yes, and I wonder why they are opposite, despite the fact that they can not (: The point is that I was thinking 'return' is part of mathematical functor mapping objects of Hack. But really return is representing natural tranformation, which is defined for every Monad. – uhbif19 Mar 03 '14 at 17:07
  • In category theory, a functor maps two things: objects to objects and arrows to arrows. In Haskell, a functor also maps two things: values to values and types to types. – David Young Mar 03 '14 at 18:00
  • 1
    Exactly, `return` is representing the natural transformation _η_: 1 → _T_, which is defined for every monad but not for general functors. So... what's still not clear to you? – leftaroundabout Mar 03 '14 at 19:02
  • @DavidYoung "values to values and types to types" ??? – uhbif19 Mar 03 '14 at 19:33
  • 1
    @leftaroundabout Yes, that is exactly that I had not understand. Now everything is clear, just SO is locking. – uhbif19 Mar 03 '14 at 19:34
  • In `instance Functor f where ...`, `f` is something that takes a type and gives you another type (so it is a mapping between types). For example `Maybe` is a type constructor that takes a type and gives you a type. If you give it `Int`, then it gives you `Maybe Int`. `fmap` maps `f a` values to `f b` values given a function `a -> b`. – David Young Mar 03 '14 at 20:03
  • @DavidYoung "fmap maps f a values to f b values given a function a -> b." interpretation is unclear to me, and is not related to mathematical definition. Why it is beter than just think fmap as map of arrows of Hask? – uhbif19 Mar 03 '14 at 20:52
  • I didn't word that very well. `fmap` takes a function from `a -> b` and maps it to a function from `f a -> f b`. As I understand it, this is analogous to the arrow mapping done by category theoretic functors. It takes an arrow in the category Hask, and it maps it to an arrow in the category Hask where all types have an `f` applied to them. So in the `Maybe` example, it maps arrows from Hask to the category of Haskell types where all types are applied to `Maybe`: `fmap :: (a -> b) -> (Maybe a -> Maybe b)`. – David Young Mar 04 '14 at 01:36

5 Answers5

16

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 α (for Functor F),
  • β -> M β (for Monad M).

Then for a functor you need a map on morphisms (i.e. functions, which are values):

fmap :: (α -> β) -> (F α -> F β)

The important thing is that return :: α -> M α of Monad is not a mapper of a type α to the M α as you might think. According to the mathematical definition of a monad, return corresponds to a natural transformation from Id functor to the M functor. And the Id functor is kind of implicit in Hask. The standard definition of a monad also requires another natural transformation M ◦ M -> M. So translating it to Haskell would look like

class Functor m => Monad m where
    return :: Id α -> m α
    join :: m (m α) -> m α

(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 from the standard bind >>= :: m α -> (α -> m β) -> m β:

(>=>) :: Monad m => (α -> m β) -> (β -> m γ) -> (α -> m γ)
f >=> g = \a => f a >>= g

You can see, that it's all actually about the Kleisli category. See also the article on nLab about monads in computer science.

laughedelic
  • 6,230
  • 1
  • 32
  • 41
8

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 Functors are endofunctors in Hask, i.e. associate types to types, by the following means:

Prelude> :k Maybe
Maybe :: * -> *
Prelude> :k Int
Int :: *
Prelude> :k Maybe Int
Maybe Int :: *

OTOH, the arrows of Hask are in fact values, of some function type a -> b. These are associated in the following way:

fmap :: ( Functor (f ::   t     ->     f t       {- type-level  -} ) )
             =>         (a->b)  ->  fmap(a->b)   {- value-level -}
                     ≡  (a->b)  ->  (f a->f b)
Community
  • 1
  • 1
leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • Yes, that is definitely what's i am talking about. Functor consists of two morphisms, but in Haskell one of them is simply function and another is type-level entity. – uhbif19 Feb 09 '14 at 16:31
  • 5
    That's not quite correct. If you'd like to see functors as _morphisms_, then it's just one: in the category of categories, the objects are categories and a morphism between category _A_ and category _B_ is a functor that maps objects of _A_ to objects of _B_ as well as morphisms of _A_ to morphisms of _B_. In the example, `Maybe` is an endofunctor of **Hask**, i.e. an endomorphism in the category of categories, and as I said it maps objects to objects (e.g. the _type_ `Int` to type `Maybe Int`) and morphisms to morphisms (`length :: String -> Int` to `fmap length :: Maybe String -> Maybe Int`) – leftaroundabout Feb 09 '14 at 16:43
6

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 (or pure or unit 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:

instance Functor [] where
   fmap f (x : xs) = f x : fmap xs
   fmap _ []       = []

instance Functor Maybe where
   fmap f (Just x) = Just (f x)
   fmap _ Nothing  = Nothing

instance Functor ((,) a) where
   fmap f (x, y) = (x, f y)

What about return for Functor now?

Lists:

instance Functor [] where
   return x = [x]

Alright. What about Maybe?

instance Functor Maybe where
   return x = Just x

Okay. Now Tuples:

instance Functor ((,) a) where
   return x = (??? , x)

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 the Unit type with only one value. But if its Bool, should we take True or False? If it is Either Int Bool should we take Left 0 or Right False or Left 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 and Monad you will see that there are indeed instances for Functor ((,) a) but not for Monad ((,) a). This is because you just can't define return for that thing.

scravy
  • 11,904
  • 14
  • 72
  • 127
4

If you have

instance Functor F where
    fmap = ...

Then the type constructor F is the action on objects (which are types) taking a type T to the type F T, and fmap is the action on morphisms (which are functions) taking a function f :: T -> U to fmap f :: F T -> F U.

Tom Ellis
  • 9,224
  • 1
  • 29
  • 54
0

In category theory, a functor maps all the objects from a category to another, but a functor doesn't map the elements in the objects.

Zim
  • 1,528
  • 1
  • 10
  • 6