簡體   English   中英

Haskell 文件讀取

[英]Haskell file reading

我最近才開始學習 Haskell,在試圖弄清楚文件讀取的工作原理時遇到了很多麻煩。

例如,我有一個包含數字行的文本文件“test.txt”:

32 4
2 30
300 5

我想閱讀每一行,然后評估每個單詞並添加它們。

因此,我正在嘗試做這樣的事情:

import System.IO
import Control.Monad

main = do
        let list = []
        handle <- openFile "test.txt" ReadMode
        contents <- hGetContents handle
        singlewords <- (words contents)
        list <- f singlewords
        print list
        hClose handle

f :: [String] -> [Int]
f = map read

我知道這是完全錯誤的,但我根本不知道如何正確使用語法。

任何幫助將不勝感激,以及鏈接到具有除例子和代碼解釋好的教程,這個我已經充分閱讀。

不錯的開始! 唯一要記住的是純函數應用程序應該使用let而不是綁定<-

import System.IO  
import Control.Monad

main = do  
        let list = []
        handle <- openFile "test.txt" ReadMode
        contents <- hGetContents handle
        let singlewords = words contents
            list = f singlewords
        print list
        hClose handle   

f :: [String] -> [Int]
f = map read

這是使事物編譯和運行所需的最小更改。 在風格上,我有幾點評論:

  1. 綁定list兩次看起來有點陰暗。 請注意,這並沒有改變值list ——而是隱藏了舊定義。
  2. 內聯純函數更多!
  3. 如果可能,使用readFile比手動打開、讀取和關閉文件更可取。

實現這些更改給出了這樣的東西:

main = do  
        contents <- readFile "test.txt"
        print . map readInt . words $ contents
-- alternately, main = print . map readInt . words =<< readFile "test.txt"

readInt :: String -> Int
readInt = read

Daniel Wagner 的解決方案是一個很好的解決方案。 這是它的另一個擺動,因此您可以獲得有關有效文件處理的更多想法。

{-#  LANGUAGE OverloadedStrings #-}
import System.IO
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Applicative
import Data.List

sumNums :: B.ByteString -> Int
sumNums s = foldl' sumStrs 0 $ B.split ' ' s

sumStrs :: Int -> B.ByteString -> Int
sumStrs m i = m+int
              where Just(int,_) = B.readInt i

main = do 
  sums <- map sumNums <$> B.lines <$> B.readFile "testy"
  print sums

首先,您將看到 OverloadedStrings 編譯指示。 這允許使用僅對實際上是字節串的字符串文字使用普通引號。 出於多種原因,我們將使用 Lazy ByteStrings 來處理文件。 首先,它允許我們通過程序流式傳輸文件,而不是一次強制將其全部放入內存中。 此外,字節串通常比字符串更快、更高效。

其他一切都非常簡單。 我們將文件讀入一個懶惰的行列表,然后在每一行上映射一個求和函數。 <$>只是允許我們對 IO() 函子內部的值進行操作的快捷方式——如果這太過分了,我深表歉意。 我的意思是,當你讀取文件時,你不會得到一個 ByteString,你會得到一個包裹在 IO 和 IO(ByteString) 中的 ByteString。 <$>表示“嘿”我想對 IO 內部的東西進行操作,然后將其包裝回去。

B.split 根據空格將每一行分成數字。 (我們也可以為此使用 B.words)唯一有趣的部分是在sumStrs我們使用解構/模式匹配從 readInt 函數返回的 Just 中提取第一個值。

我希望這可以幫到你。 詢問您是否有任何問題。

對於所有非功能性程序員來說,這里是一種享受

unsafePerformIO . readFile $ "file.txt"

將文件讀入字符串

沒有 IO 字符串,只是一個普通的滿載字符串可供使用。 這可能不是正確的方法,但它有效,無需更改現有函數以適應 IO String

ps 不要忘記導入

import System.IO.Unsafe 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM