
On Wed, Aug 19, 2009 at 11:57:47PM +0100, Simon Parry wrote:
Thanks Jan, very helpful and you're right I am just trying to combine 2 lists; one with 'wrapped' values, one without.
You can write your own version of `liftM2` (from `Control.Monad`) like this:
liftM2snd f a mb = do { b <- mb; return (f a b) }
so the b <- mb bit is 'unwrapping' the Maybe b to use it with the pure function f?
That's correct. In fact it is just a syntactic abbreviation (sugar) for liftM2snd f a mb = mb >>= \b -> return (f a b) You can always rewrite expressions with `do` using just `>>=`, `>>`, and `->`. (Note that `<-` becomes the “dot” `->`.)
I guess I didn't realise this as I've only seen it in the IO monad, but naturally it would work with all monads.
You can verify that
liftM2snd == (fmap .)
if I look at this in GHCi the liftM2snd acts over monads and the (fmap .) acts over functors. Now I'm still trying to get comfortable with simple monad manipulations so maybe I should just read this as functors are equivalent to monads and not worry too much about it yet? With that in mind fmap acts to map some pure function over a 'wrapped' value?
Every Monad is automatically a Functor as well. You can define `fmap` using monadic operations: fmap f ma = ma >>= return . f Anyway, for some reasons this is not done automatically. You can do it automatically with some GHC extensions. Load this into GHCi (don't forget the first line): {-# OPTIONS -XFlexibleInstances -XUndecidableInstances #-} instance Monad m => Functor m where fmap f ma = ma >>= return . f And here we go (in my GHCi 6.10.4): *Main> :t fmap fmap :: (Monad f) => (a -> b) -> f a -> f b Usually, however, you don't need to do this because all instances of Monad are already instances of Functor. Also note that fmap :: (Functor f) => (a -> b) -> f a -> f b holds as well, that is, the type of `fmap` is ambiguous (because of the GHC extensions above). Sincerely, Jan. -- Heriot-Watt University is a Scottish charity registered under charity number SC000278.