Sunday, February 15, 2009

A comment on Parameterized Monads

This post was really intended to be just a comment to another blog post, but since I wanted to include some code it turned out to be better to write a little post myself. sigfpe has a nice post about Parameterized Monads, which pop up naturally ones you've done a bit of monadic programming. He argues that the ordinary Monad concept we have in Haskell is the wrong one, Paramterized Monads fall out so naturally that they ought to be the default. He then goes on to say "At the very least, do-notation needs to be adapted to support ParameterisedMonad." But GHC already supports do-notation for Parameterized Monads! Here's a proof:

> {-# LANGUAGE NoImplicitPrelude #-}
> module PMonad where

> import Prelude (fromInteger,(+),(*),show)

> class PMonad m where
>   return :: a -> m s s a
>  (>>=)  :: m s1 s a -> (a -> m s s2 b) -> m s1 s2 b
>   (>>)   :: m s1 s2 a -> m s2 s3 b -> m s1 s3 b
>   fail   :: m s1 s2 a

> data State s1 s2 a = State { runState :: s1 -> (a,s2) }

> instance PMonad State where
>   return a = State (\s -> (a,s))
>   f >>= m  = State (\s1 ->
>              case runState f s1 of
>                (a,s2) -> runState (m a) s2)
>   m1 >> m2 = m1 >>= \_ -> m2
>   fail     = fail

> get   = State (\s -> (s,s))
> put s = State (\_ -> ((),s))

> test1 = do x <- return 1
>            y <- return 2
>            z <- get
>            put (x+y*z)
>            return z

> go1 = runState test1 10

> test2 = do x <- return 1
>            y <- return 2
>            z <- get
>            put (show (x+y*z))
>            return z

> go2 = runState test2 10

[1 of 1] Compiling PMonad           ( PMonad.hs, interpreted )
Ok, modules loaded: PMonad.
*PMonad> go2
(10,"21")
And there you go. It's the NoImplicitPrelude that does the trick.