How to mix Haskell monadic and pure filters in a piping fashion?

haskell, operator-keyword, pipe

Solution

Ugh. As simple as this:

infixl 1 |>=
(|>=) = flip fmap

findFiles target = 
  getDirectoryContents target           |>=
  filter (not . (=~ "[0-9]{8}\\.txt$")) |>=
  filter (=~ "\\.txt$")                 >>=
  filterM doesFileExist                 >>=
  mapM canonicalizePath

Problem

In a previous question, I tried to ask about how to mix pure and monadic functions by piping them together, but because I may have worded my question wrong and my example was too simplistic, I think the discussion went the wrong direction, so I think I'll try again. Here is an example function that mixes pure and monadic filters. In this example, there are some pure filters sequenced in-between monadic filters to try to reduce the amount of work. ``` findFiles target = getDirectoryContents target >>= return . filter (not . (=~ "[0-9]{8}\\.txt$")) >>= return . filter (=~ "\\.txt$") >>= filterM doesFileExist >>= mapM canonicalizePath ``` The benefit of writing it this way, where pure functions are mixed in using `return`, is that there is a visual flow of data from top to bottom. No need for temporary variables, `fmap`, `<$>` or the like. Ideally, I can get rid of the `return`s to make it cleaner. I had the idea of using some operator: ``` (|>=) :: Monad m => a -> (a -> m b) -> m b a |>= b = (return a) >>= b ``` But I don't know how to write this function to avoid operator precedence problems. Does this already exist? It is similar to `<$>` but the "other direction". If not, how do I make this operator work? More generally, is there a good way to write code in this piping fashion, or need I settle for `fmap`s and temporary variables like as described in my previous question?

Original source