Get list of the executables in the current directory This is what I've done;

import Control.Applicative
import Control.Monad
import qualified System.Directory as SD
main = do
    files &lt;- SD.getDirectoryContents =&lt;&lt; SD.getCurrentDirectory
    exes &lt;- filterM (liftA SD.executable &lt;$&gt; SD.getPermissions) files
    print exes


This works fine, but I can't help feeling that this code is somewhat redundant --- with filterM, liftA, &lt;$&gt; and =&lt;&lt; all present at once, things seem unnecessarily complicated.

How can I improve this piece of code?

For a quick reference:

SD.getCurrentDirectory :: IO FilePath
SD.getDirectoryContents :: FilePath -&gt; IO [FilePath]
SD.executable :: Permissions -&gt; Bool
SD.getPermissions :: FilePath -&gt; IO Permissions


and I want to filter the contents of the current directory based on its being executable or not.
I wouldn't import System.Directory qualified, it doesn't export anything that could clash with standard names.

import Control.Applicative
import Control.Monad
import System.Directory

main :: IO ()
main = do
    files &lt;- getDirectoryContents =&lt;&lt; getCurrentDirectory
    exes &lt;- filterM (liftA executable &lt;$&gt; getPermissions) files
    print exes


You can toss out the Functor and Applicative stuff and just compose Monads.

import Control.Monad
import System.Directory

main :: IO ()
main = do
    files &lt;- getDirectoryContents =&lt;&lt; getCurrentDirectory
    exes &lt;- filterM (liftM executable . getPermissions) files
    print exes


You could also get rid of reverse bind and use the forward version, it's maybe more familiar?

import Control.Monad
import System.Directory

main :: IO ()
main = do
    files &lt;- getCurrentDirectory &gt;&gt;= getDirectoryContents
    exes &lt;- filterM (liftM executable . getPermissions) files
    print exes


I'd eliminate the explicit use of bind entirely though, then it becomes easier to turn this into a function that can work on directories other than the current one.

import Control.Monad
import System.Directory

main :: IO ()
main = do
    dir &lt;- getCurrentDirectory
    printExecutables dir

printExecutables :: FilePath -&gt; IO ()
printExecutables dir = do
    files &lt;- getDirectoryContents dir
    exes &lt;- filterM (liftM executable . getPermissions) files
    print exes