
I asked "How is IO a functor"? On 3 Aug 2007, at 11:50 am, Dan Piponi wrote:
IO is a fully paid up Monad in the categorical sense. The category is the category whose objects are types and whose arrows are functions between those types. IO is a functor. The object a maps to IO a. An arrow f::a->b maps to (>>= return . f)::IO a -> IO b and that can be used to make IO an instance of Functor. The natural transforms eta and mu are called return and join.
Please go over this again, but slowly this time. You have convinced me, but I'd like to understand the details a little better. I see that any type constructor TC :: * -> * is halfway to being a functor on this category of types. It acts on the objects in the obvious way, so the next step is to see about the arrows. If f :: a -> b then we want TC f :: TC a -> TC b such that TC (f . g) = TC f . TC g and TC (id::a->a) = id :: TC a -> TC a Now this is precisely the Haskell Functor class, so TC is the object part and fmap is the arrow part. You say that (>>= return . f) can be used to make [a Monad] an instance of Functor. Try it... by golly it's true. I see: fmap f = (>>= return . f). So why *aren't* Monads already set up using the type class machinery to always *be* Functors in Haskell? Isn't it bound to confuse people if monads are functors but Monads are not Functors? This is especially puzzling because Maybe, [], and IO already *are* Functors, but the way this is done makes it look accidental, not like the fundamental property of Monads it apparently is. (By the way, I note that the on-line documentation for Control.Monad glosses
= as "Sequentially composes two actions...".)