
Haskellians,
i am delighted to see vigorous exchange that actually resulted in change of
positions. i confess i was going to give up, but glad others stepped into
the breach. This is yet another indication of what an unusual community this
is.
Best wishes,
--greg
Date: Fri, 3 Aug 2007 13:43:32 +1200
From: ok
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...".)
-- L.G. Meredith Managing Partner Biosimilarity LLC 505 N 72nd St Seattle, WA 98103 +1 206.650.3740 http://biosimilarity.blogspot.com