{- 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/

It was already difficult to teach monads to 2nd year functional programming students, and the new definition seems to be designed to make them deliberately incomprehensible.
2/

The whole point of monads presented as Kleisli triples, which is what Monad' amounts to, is to avoid having to define and prove functoriality and naturality.

The new Haskell definition misses this point.

Moreover, "Applicative" is a distraction.

It is used sometimes, but only very occasionally, and, more importantly, it is hardly at the core of the definition of monad.

In fact, here we have it only because our monads (in either form) are internally defined and hence automatically strong as we are working in something that looks more or less like a cartesian closed category (but it really isn't a cartesian closed category, as the universal property of exponentials for function types doesn't really hold (meaning that it fails).)

3/

@MartinEscardo

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

?

Sign in to participate in the conversation
Mastodon

a Schelling point for those who seek one