问题描述
我试图在Haskell中编写一个简单的
你的问题是 exitWith 会终止整个程序。所以,你不能真的使用 forever 来遍历文件,因为显然你不想运行forever函数,直到文件结束。您可以像这样重写 catHandle
catHandle :: Handle - > IO()
catHandle H =做
EOF< - IO.hIsEOF H
如果EOF然后做
H关闭H
,否则
hGetLine h取代; > = putStrLn
catHandle h
Ie如果我们还没有达到EOF,我们会递归并读取另一行。
然而,这种方法过于复杂。您可以简单地将cat写为main = do
文件< - getArgs
forM_文件$ \\ \\文件名 - >做
内容< - readFile文件名
putStr内容
由于懒惰我/ o,整个文件内容并没有真正加载到内存中,而是流入标准输出。
如果您对 Control中的运算符感到满意。 Monad ,整个程序可以缩短为
main = getArgs>> = mapM_ (readFile> => putStr)
I am trying to write a simple cat program in Haskell. I would like to take multiple filenames as arguments, and write each file sequentially to STDOUT, but my program only prints one file and exits.
What do I need to do to make my code print every file, not just the first one passed in?
import Control.Monad as Monad import System.Exit import System.IO as IO import System.Environment as Env main :: IO () main = do -- Get the command line arguments args <- Env.getArgs -- If we have arguments, read them as files and output them if (length args > 0) then catFileArray args -- Otherwise, output stdin to stdout else catHandle stdin catFileArray :: [FilePath] -> IO () catFileArray files = do putStrLn $ "==> Number of files: " ++ (show $ length files) -- run `catFile` for each file passed in Monad.forM_ files catFile catFile :: FilePath -> IO () catFile f = do putStrLn ("==> " ++ f) handle <- openFile f ReadMode catHandle handle catHandle :: Handle -> IO () catHandle h = Monad.forever $ do eof <- IO.hIsEOF h if eof then do hClose h exitWith ExitSuccess else hGetLine h >>= putStrLn
I am running the code like this:
runghc cat.hs file1 file2
Your problem is that exitWith terminates the whole program. So, you cannot really use forever to loop through the file, because obviously you don't want to run the function "forever", just until the end of the file. You can rewrite catHandle like this
catHandle :: Handle -> IO () catHandle h = do eof <- IO.hIsEOF h if eof then do hClose h else hGetLine h >>= putStrLn catHandle h
I.e. if we haven't reached EOF, we recurse and read another line.
However, this whole approach is overly complicated. You can write cat simply as
main = do files <- getArgs forM_ files $ \filename -> do contents <- readFile filename putStr contents
Because of lazy i/o, the whole file contents are not actually loaded into memory, but streamed into stdout.
If you are comfortable with the operators from Control.Monad, the whole program can be shortened down to
main = getArgs >>= mapM_ (readFile >=> putStr)
这篇关于我如何在Haskell中实现`cat`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!