2016-04-25 110 views
2

即時嘗試製作一個應該逐行讀取文件的程序,並檢查它是否爲palindrom,如果是,則打印。如何從Haskell中的一個文件逐行讀取

我真的很新的哈斯克爾,所以我唯一可以做的事情就是剛剛打印出的每一行,使用此代碼:

main :: IO() 
    main = do 
    filecontent <- readFile "palindrom.txt" 
    mapM_ putStrLn (lines filecontent) 

isPalindrom w = w==reverse w 

的事情是,我不知道如何通過線走線和檢查行是否是一個迴文(請注意,在我的文件中,每行只包含一個字)。謝謝你的幫助。

回答

3

看看filter函數。您可能不希望將所有處理放在一行上,但使用表達式。另外,你的縮進熄滅:

main :: IO() 
main = do 
    filecontent <- readFile "palindrom.txt" 
    let selected = filter ... filecontent 
    ... 
+0

你能寫出完整的代碼嗎?即時通訊絕對是新的,所以我不知道如何繼續.. –

2

這裏有一個建議的方法

main :: IO() 
main = do 
    filecontent <- readFile "palindrom.txt" 
    putStrLn (unlines $ filter isPalindrome $ lines filecontent) 

isPalindrome w = w==reverse w 

括號中的部分是純粹的代碼,它的類型是String->String。儘可能多地分離純代碼通常是一個好主意,因爲代碼往往是最容易推理的,並且通常更容易重用。

您可以將該部分中的數據視爲從右向左流動,由($)運算符分解。首先你將內容分成不同的行,然後只過濾迴文,最後以字符串的形式重建完整的輸出。另外,由於Haskell是懶惰的,即使它看起來像是將內存中的輸入視爲單個String,但實際上它只是根據需要提取數據。


編輯以添加額外的信息....

OK,所以SOLN的心臟是純粹的部分:

unlines $ filter isPalindrome $ lines filecontent 

的方式,($)作品是通過評估功能在右邊,然後用它作爲左邊東西的輸入。在這種情況下,filecontent是文件的全部輸入(包括換行符的String),輸出是STDOUT(也是包含換行符的完整字符串)。

讓我們跟隨樣本輸入通過這個過程中, 「ABCBA \ N1234 \了nK」

unlines $ filter isPalindrome $ lines "abcba\n1234\nK" 

首先,線將打入線的陣列此

unlines $ filter isPalindrome ["abcba", "1234", "K"] 

注意,線的輸出正被輸入到濾波器的輸入端。

那麼,過濾器是做什麼的?注意其類型

filter :: (a -> Bool) -> [a] -> [a] 

這需要2輸入參數,可以首先是一個函數(isPalendrome是),項目的第二列表。它將使用該函數測試列表中的每個項目,並且其輸出是相同的列表輸入,減去函數已選擇刪除的項目(返回False)。在我們的案例中,第一項和第三項實際上是古典的,第二項沒有。我們的表達式的計算結果如下

unlines ["abcba", "K"] 

最後,unlineslines相反....它將再次concatinate的項目,在間插入換行。

"abcba\nK" 

由於STDIO本身是String,因此可以輸出。

注意,是它完美地確定以輸出的使用非純函數String秒的列表,如下所示

forM ["1", "2", "3"] $ \item -> do 
    putStrLn item 

然而,該方法混合純和不純的代碼,並且被認爲是略小於慣用Haskell代碼比前者。儘管如此,你仍然會看到這種類型的東西!

+0

嗨,感謝您的幫助,請你解釋一下關於「$」操作符和函數過濾器如何工作? 據我瞭解,過濾器檢查,如果「isPalindrome」在filecontents的每一行,如果屬實,那麼打印,對不對?那麼,爲什麼我需要在這裏不成立? 非常感謝! –

+1

我已經添加了更多細節。 – jamshidh

+0

太好了! , 謝謝 ! –