Skip to content

Instantly share code, notes, and snippets.

@qpliu
Created March 18, 2011 03:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qpliu/875594 to your computer and use it in GitHub Desktop.
Save qpliu/875594 to your computer and use it in GitHub Desktop.
Exploring lists as instances of MonadPlus in Haskell by implementing filter
> import Control.Monad(MonadPlus(mzero),liftM,unless)
The regular filter can be implemented recursively:
> f1 _ [] = []
> f1 test (a:as) | test a = a : f1 test as | otherwise = f1 test as
Or the recursion can be abstracted:
> f2 test list = foldr (\ a rest -> if test a then a : rest else rest) [] list
Since a list is an instance of MonadPlus, implement generalized filter, which also works with Maybe:
> f3 test list = do { a <- list; if test a then return a else mzero }
Now, for some gratuitous obfuscation:
Replace the if with unless:
> f4 test list = do { a <- list; liftM (const a) (unless (test a) mzero) }
Remove the do notation:
> f4' test list = list >>= \ a -> liftM (const a) (unless (test a) mzero)
Converting to point-free, using the S combinator:
> f4'' test list = list >>= s (liftM . const) (flip unless mzero . test)
> where s t u v = t v (u v)
> f4''' test = (>>= s (liftM . const) ((flip unless mzero .) test)
> where s t u v = t v (u v)
Finally:
> f5 :: MonadPlus m => (a -> Bool) -> m a -> m a
> f5=flip(>>=).s(liftM.const).(flip unless mzero.)where s t u v=t v(u v)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment