MonadNum

module MonadNum where instance (Show (m n), Eq (m n), Monad m, Num n) => Num (m n) where a + b = do a' <- a b' <- b return $ a' + b' a - b = do a' <- a b' <- b return $a' - b' a * b = do a' <- a b' <- b return $ a' * b' negate = (>>= return . negate) abs = (>>= return . abs) signum = (>>= return . signum) fromInteger = return . fromInteger

This little hack lets you use Monads that are wrapping Nums work like Nums directly. So for example, you can do fun stuff like:

*MonadNum> [1,2,3] * 3 [3,6,9] *MonadNum> [1,2,3,4] * [5,6] [5,6,10,12,15,18,20,24] *MonadNum> [[1,2],[3,4]] * [5,6] [[5,10],[6,12],[15,20],[18,24]] *MonadNum> Just 3 + Just 4 Just 7 *MonadNum> Just 3 + Nothing Nothing

And, if you don’t mind delving into the ill-advised, you can add these instances:

import System.IO.Unsafe instance (Show a) => Show (IO a) where show x = show $ unsafePerformIO x {-# NOINLINE show #-} instance (Eq a) => Eq (IO a) where m == n = unsafePerformIO $ do m' <- m n' <- n return $ m' == n' {-# NOINLINE (==) #-}

And that allows you to do really, really dumb stuff like this:

*MonadNum Control.Monad> b <- (liftM read getLine) + (liftM read getLine) 14 15 *MonadNum Control.Monad> b 29 *MonadNum Control.Monad> getLine == getLine hello there False

Woo, I’m exhausted from having all this fun…