In this set of slides by Jim Duey at slide 13 - he suggests that all Monads are applicative functors.
In the Haskell 7.7 compiler output - I'm seeing the following (another example is here):
‛Parser’ is an instance of Monad but not Applicative - this will become an error in GHC 7.10, under the Applicative-Monad Proposal.
Does this mean the Haskell Compiler currently tolerates Monads that are not applicative functors - but the plan is to correct this?
An applicative is a data type that implements the Applicative typeclass. A monad is a data type that implements the Monad typeclass. A Maybe implements all three, so it is a functor, an applicative, and a monad.
Like monads, applicative functors are functors with extra laws and operations; in fact, Applicative is an intermediate class between Functor and Monad .
Functor in Haskell is a typeclass that provides two methods – fmap and (<$) – for structure-preserving transformations. To implement a Functor instance for a data type, you need to provide a type-specific implementation of fmap – the function we already covered.
Another simple example of a functor is the Maybe type. This object can contain a value of a particular type as Just , or it is Nothing (like a null value).
Right now Applicative
isn't a superclass of Monad
instance Monad m where ... -- this is how it is today, instead of
instance Applicative m => Monad m where ...
but it is planned so that in GHC 7.10 this will be changed so that Applicative
is a superclass of Monad
. In order to help the transition, in GHC 7.7 and 7.8 there will be the warning you saw issued whenever GHC encounters a Monad
without an Applicative
instance.
Now the slightly confusing bit is that all valid Monad
s are applicative functors, even if they're not instance
s of Applicative
. We can write
fmapM :: Monad m => (a -> b) -> m a -> m b
fmapM f ma = ma >>= return . f -- a.k.a. `liftM`
pureM :: Monad m => a -> m a
pureM = return
ap :: Monad m => m (a -> b) -> m a -> m b
ap mf ma = do { f <- mf; a <- ma; return (f a) } -- a.k.a. `ap`
which together satisfy the signature and laws of Functor
and Applicative
. This is why the superclass constraint makes sense to add and it's purely historical accident that it wasn't there in the first case—Applicative
s were discovered and popularized far after Monad
s were.
newtype WrappedMonad m a = WM (m a)
instance Monad m => Functor (WrappedMonad m) where
fmap f (WM m) = WM (liftM f m)
instance Monad m => Applicative (WrappedMonad m) where
pure = WM . return
WM mf <*> WM ma = WM $ mf `ap` ma
For more information on how Applicative
and Monad
relate, take a look at an answer I wrote previously here: Is it better to define Functor in terms of Applicative in terms of Monad, or vice versa?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With