
On Tuesday 04 January 2011 5:24:21 am oleg@okmij.org wrote:
Method A: just define bind as usual
instance (Functor (Iteratee el m),Monad m) => Monad (Iteratee el m) where
return = IE_done
IE_done a >>= f = f a IE_cont e k >>= f = IE_cont e (\s -> k s >>= docase)
where docase (IE_done a, stream) = case f a of
IE_cont Nothing k -> k stream i -> return (i,stream)
docase (i, s) = return (i >>= f, s)
Although we must state the constraint (Functor (Iteratee el m)) to satisfy the super-class constraint, we have not made any use of the constraint.
This, at least, is false. If Functor is a superclass of Monad, then Monad m implies Functor m, which implies Functor (Iteratee el m). So Monad m is a sufficient constraint for the instance. As for the other concerns, I think the closest fix I've seen is to allow subclasses to specify defaults for superclasses, and allow instances for subclasses to include methods for superclasses. So: class Functor m => Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b fmap f x = x >>= return . f This has its own caveats of course. And in this case, it seems to overconstrain the functor instance, since presumably we'd end up with: instance Monad m => Monad (Iteratee el m) where ... ==> instance Monad m => Functor (Iterate el m) where ... I'm not sure what to do about that. -- Dan