Haskell uses a lot of ideas from category theory, but the correspondence between Haskell and category theory can be a little hard to see at times.
One difficulty is that although Haskell articles use terms like functor and monad from category theory, they seldom actually talk about categories per se. If we’ve got functors, where are the categories? (This reminds me of Darth Vader asking “If this is a consular ship, where is the ambassador?”)
In Haskell literature, everything implicitly lives Hask, the category of Haskell types, or in some subcategory of Hask. This means that the category itself is not the focus of attention. In category theory, functors often operate between very different classes of objects, such as topological spaces and their fundamental groups, and so it’s more important to state what category something lives in.
Another potential stumbling block is to think of Haskell types as categories and values as objects. That would be reasonable, since in computer science an “object” is an instance of a type. But the right correspondence is to think of Haskell types as categorical objects. Instances of types are below the level of abstraction we’re working at. This is analogous to how category theory treats objects as black boxes with no way to talk about what’s inside.
Finally, Haskell monads look a little different from categorical monads. Haskell’s
return corresponds directly to unit, usually written as η, in category theory. But Haskell monads have a bind operator
>>= while mathematical monads have a join operator μ. These are not equivalent, though you can implement each in terms of the other:
join :: Monad m => m (m a) -> m a join x = x >>= id (>>=) :: Monad m => m a -> (a -> m b) -> m b x >>= f = join (fmap f x)
To read more along these lines, see the Wikibooks article on Haskell and Category theory.
Update: Stephen Diehl suggested I mention the differences between the idealized category Hask and the implementation of the Haskell language. These are discussed here.