外部コマンドの実行結果を受け取るには

そういえばどうやるんだろうと思って、調べてみました。
サンプルプログラム。ls -aを実行して、その結果を加工して表示します。

module Main (main) where

import System.IO (hGetContents)
import System.Process (runInteractiveProcess, waitForProcess)

main :: IO ()
main = do
  (_, out, _, procHandle) <- runInteractiveProcess "ls" ["-a"] Nothing Nothing
  putStr . unlines . map (\ l -> "<" ++ l ++ ">") . lines =<< hGetContents out
  waitForProcess procHandle
  return ()

実行例:

$ ls -a1
.
..
a.hs
$ runghc -W a.hs
<.>
<..>
<a.hs>

(追記) リファクタリングしました。演算子に分離してみました。これは変態的です。

module Main (main) where

import System.IO (hGetContents)
import System.Process (runInteractiveProcess, waitForProcess)

(%%%) :: FilePath -> [String] -> IO String
(%%%) cmd args = do
  (_, out, _, procHandle) <- runInteractiveProcess cmd args Nothing Nothing
  s <- hGetContents out
  waitForProcess procHandle
  return s

main :: IO ()
main = putStr . unlines . map (\ l -> "<" ++ l ++ ">") . lines
         =<< "ls" %%% ["-a"]

参照: 第5回 ListではなくMaybeを使う意義(2ページ目) | 日経 xTECH(クロステック)