我如何在Haskell中实现

我如何在Haskell中实现

本文介绍了我如何在Haskell中实现`cat`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在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`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 17:23