Skip to content

Instantly share code, notes, and snippets.

@puffnfresh
Created May 9, 2013 20:38
Show Gist options
  • Save puffnfresh/5550437 to your computer and use it in GitHub Desktop.
Save puffnfresh/5550437 to your computer and use it in GitHub Desktop.
Monad is a monoid.
class Monoid m where
mappend :: m -> m -> m
mempty :: m
mconcat :: Monoid m => [m] -> m
mconcat = foldr mappend mempty
newtype MonadMonoid m a =
MonadMonoid { getMonad :: a -> m a }
instance Monad m => Monoid (MonadMonoid m a) where
mappend f g = MonadMonoid (\a -> getMonad f a >>= getMonad g)
mempty = MonadMonoid return
validations :: [MonadMonoid Maybe String]
validations = fmap MonadMonoid [
\x -> if x == "Bad" then Nothing else Just x
, \x -> if x == "Invalid" then Nothing else Just x
]
main :: IO ()
main = do
print . getMonad (mconcat validations) $ "Bad"
print . getMonad (mconcat validations) $ "Invalid"
print . getMonad (mconcat validations) $ "Good!"
{-
Nothing
Nothing
Just "Good!"
-}
@mergeconflict
Copy link

You can also use Kleisli from Control.Arrow and generalize:

import Prelude hiding ((.), id)
import Control.Category
import Data.Monoid

newtype EndoCat c a = EndoCat (c a a)
instance Category c => Monoid (EndoCat c a) where
    mempty = EndoCat id
    EndoCat lhs `mappend` EndoCat rhs = EndoCat $ lhs . rhs

See also http://comonad.com/haskell/monoids/dist/doc/html/monoids/Data-Monoid-Categorical.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment