2013-01-12 50 views
1

我在考試前試圖學習Haskell,它對我來說仍然很神奇。今天,我試圖編寫一個程序,它讀取一個文件,並將它的行按照順序寫入另一個文件。結果? 。錯誤:(大量的這裏是我的代碼:文件中的反轉行

import IO 

readLines :: Handle -> [String] -> [String] 
readLines handler list = do 
    eof <- hIsEOF handler 
    if eof then list 
     else do 
      line <- hGetLine handler 
      readLines handler (list ++ [line]) 

writeLines :: Handle -> [String] -> [String] 
writeLines handler list = if length list == 0 then list 
    else do 
     line <- head list 
     hPutStrLn handler line 
     writeLines tail list 

fileToList :: FilePath -> [String] 
fileToList filename = do 
    handler <- openFile filename ReadMode 
    list <- (readLines handler []) 
    hClose handler 
    list 

invLines :: FilePath -> FilePath -> IO() 
invLines input output = do 
    handler <- openFile output WriteMode 
    inverted <- reverse (fileToList input) 
    writeLines handler inverted 
    hClose handler 

main = invLines "in.txt" "out.txt" 

我會很感激,如果你可以給我解釋一下我的錯誤

回答

6

好吧首先,

IO ==> System.IO 

接下來讓我們來看看readlines方法(PS READFILE會很好的工作在這裏)

readLines :: Handle -> [String] -> [String] --You have to return an IO [String] here. 
    readLines handler list = do 
    eof <- hIsEOF handler 
    if eof then return list --Return an IO list 
     else do 
      line <- hGetLine handler 
      readLines handler (list ++ [line]) 

下一頁到writeLines(PS writeFile也將幫助)

writeLines :: Handle -> [String] -> [String] -- You have to return IO of something, I'd recommend(). 
writeLines handler list = if length list == 0 
    then list --Change to return() 
    else do 
     line <- head list --Should be let here. Like let line = head list 
     hPutStrLn handler line 
     writeLines tail list -- Should be writeLines handler $ tail list instead. 

接下來是fileToList

fileToList :: FilePath -> [String] --Has to be IO [String] 
fileToList filename = do 
    handler <- openFile filename ReadMode 
    list <- (readLines handler []) 
    hClose handler 
    list -- Have to use return list 

哦,你好像反轉線的兩倍,因此你實際上有非常大的複製程序結束,在那裏移除反向和你會得到正確的結果。

守則在結束

import System.IO 

readLines :: Handle -> [String] -> IO [String] 
readLines handler list = do 
    eof <- hIsEOF handler 
    if eof 
    then return list 
    else do 
     line <- hGetLine handler 
     readLines handler (line:list) 

writeLines :: Handle -> [String] -> IO() 
writeLines handler list = if length list == 0 then return() 
    else do 
     let line = head list 
     hPutStrLn handler line 
     writeLines handler $ tail list 

fileToList :: FilePath -> IO [String] 
fileToList filename = do 
    handler <- openFile filename ReadMode 
    list <- (readLines handler []) 
    hClose handler 
    return list 

invLines :: FilePath -> FilePath -> IO() 
invLines input output = do 
    handler <- openFile output WriteMode 
    inputLines <- fileToList input 
    writeLines handler inputLines 
    hClose handler 

main = invLines "in.txt" "out.txt" 

,及使用該庫的改寫:

invLines input output = do 
    inputLines <- readFile input 
    writeFile output . unlines . reverse . lines $ inputLines 

invLines2 input output = 
    readFile input >>= writeFile output . unlines . reverse . lines 

大的教訓不能將IO do內從恢復正常功能塊。你必須返回一個IO東西