Created
March 18, 2011 03:50
-
-
Save qpliu/875594 to your computer and use it in GitHub Desktop.
Exploring lists as instances of MonadPlus in Haskell by implementing filter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> 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