{- I think I am going to teach Haskell monads like this next year. -}
{-# Language UndecidableInstances #-}
{- Original definition of Haskell monad. -}
class Monad' m where
return' :: a -> m a
bind' :: m a -> (a -> m b) -> m b
{- Nonsense new definition. -}
{-
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
return = pure
-}
{- We get a Monad from a Monad'. -}
instance Monad' m => Monad m where
(>>=) = bind'
{- This is because we can always define Functor and Applicative as follows. -}
instance Monad' m => Functor m where
fmap f xm = do
x <- xm
pure (f x)
instance Monad' m => Applicative m where
pure = return'
fm <*> xm = do
f <- fm
x <- xm
pure (f x)
{- Example. An economic definition of the Maybe monad. -}
data Maybe' a = Nothing' | Just' a
instance Monad' Maybe' where
return' = Just'
bind' Nothing' f = Nothing'
bind' (Just' x) f = f x
{- To test this, define a function using Monad rather than Monad'. -}
fibm :: Monad m => Integer -> m Integer
fibm 0 = pure 0
fibm 1 = pure 1
fibm n = do
x <- fibm (n-2)
y <- fibm (n-1)
pure (x+y)
{- We can use it with the Maybe' Monad automatically derived from the Maybe' Monad'. -}
fib11 :: Maybe' Integer
fib11 = fibm 11
1/
On the off chance you're not already aware and that it helps: do you know you can write
import Control.Monad
instance Monad M where ...
instance Functor M where fmap = liftM
instance Applicative M where pure = return; liftA2 = liftM2
?