Haskell中的条件标准句柄重定向

时间:2016-07-09 16:53:00

标签: haskell io monads io-redirection

我想读取文件,处理它,并将结果写入另一个文件;输入文件名将通过控制台参数提供,输出文件名由输入文件名生成。

如果没有提供参数,我希望它能透明地“故障转移”到stdin / stdout;实质上,如果提供了文件名,我将stdin / stdout重定向到相应的文件名,这样我就可以透明地使用 interact 是否提供了文件名。

这里的代码与多余的 else 中的虚拟输出一起被黑了。这样做的恰当的,惯用的形式是什么?

这可能与Control.Monad的 后卫有关,正如在类似的问题中指出的那样,但也许有人写了这个已经

import System.IO
import Data.Char(toUpper)
import System.Environment
import GHC.IO.Handle

main :: IO ()
main = do
       args <- getArgs
       if(not $ null args) then
        do
           print $ "working with "++ (head args)
           finHandle <- openFile (head args) ReadMode --open the supplied input file
           hDuplicateTo finHandle stdin --bind stdin to finName's handle
           foutHandle <- openFile ((head args) ++ ".out") WriteMode --open the output file for writing
           hDuplicateTo foutHandle stdout --bind stdout to the outgoing file
        else print "working through stdin/redirect" --get to know 
        interact ((++) "Here you go---\n" . map toUpper)

2 个答案:

答案 0 :(得分:1)

这对我来说似乎相当惯用。我有一个注意事项是避免head,因为它是一个不安全的函数(它可能会引发运行时错误)。在这种情况下,使用case进行模式匹配非常容易。

main :: IO ()
main = do
  args <- getArgs
  case args of
    fname:_ -> do
      print $ "working with " ++ fname
      finHandle <- openFile fname ReadMode
      hDuplicateTo finHandle stdin
      foutHandle <- openFile (fname ++ ".out") WriteMode
      hDuplicateTo foutHandle stdout
    [] -> do
      print "working through stdin/redirect"
  interact ((++) "Here you go---\n" . map toUpper)

答案 1 :(得分:1)

interact没有什么特别之处 - 这是它的定义:

interact        ::  (String -> String) -> IO ()
interact f      =   do s <- getContents
                       putStr (f s)

这样的事情怎么样:

 import System.Environment
 import Data.Char

 main = do
   args <- getArgs
   let (reader, writer) =
        case args of
          []         -> (getContents, putStr)
          (path : _) -> let outpath = path ++ ".output"
                        in (readFile path, writeFile outpath)
   contents <- reader
   writer (process contents)

 process :: String -> String
 process = (++) "Here you go---\n" . map toUpper

根据命令行参数,我们将readerwriter设置为IO-actions,它将读取输入并写入输出。