Haskell文件读取

Dus*_*nny 27 haskell words file

我刚刚开始学习Haskell,我在尝试弄清楚文件读取的工作方式时遇到了很多麻烦.

例如,我有一个文本文件"test.txt"它包含数字行,例如:

32 4
2 30
300 5
Run Code Online (Sandbox Code Playgroud)

我想阅读每一行,然后评估每个单词并添加它们.因此,我到目前为止尝试做这样的事情:

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
Run Code Online (Sandbox Code Playgroud)

我知道这是完全错误的,但我根本不知道如何正确使用语法.任何帮助将不胜感激.除了这个代码的示例和解释之外的好教程的链接:http: //learnyouahaskell.com/input-and-output我已经完全阅读了它

Dan*_*ner 55

不错的开始!唯一要记住的是纯函数应用程序应该使用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
Run Code Online (Sandbox Code Playgroud)

这是使事物编译和运行所需的最小变化.在风格上,我有一些评论:

  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
Run Code Online (Sandbox Code Playgroud)


Eri*_*ton 9

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
Run Code Online (Sandbox Code Playgroud)

首先,您将看到OverloadedStrings编译指示.这允许使用实际上是字节串的字符串文字的常规引号.我们将使用Lazy ByteStrings处理文件有几个原因.首先,它允许我们通过程序流式传输文件,而不是一次性将其全部压入内存.此外,字节串通常比字符串更快,更有效.

其他一切都非常简单.我们将文件文件归待为一个懒惰的行列表,然后在每一行上映射求和函数.这<$>只是允许我们操作IO()仿函数内部值的快捷方式 - 如果这太多了,我道歉.我只是说当你readFile你没有得到一个ByteString时,你得到一个包含在IO中的ByteString IO(ByteString).该<$>说"嗨"我想在IO里面的东西进行操作,然后把它包备份.

B.split根据空格将每一行分成数字.(我们也可以使用B.words这个)唯一另一个有趣的部分是sumStrs我们使用解构/模式匹配来提取readInt函数返回的Just的第一个值.

我希望这可以帮到你.问你是否有任何问题.

  • 谢谢!你的方法有很多我不熟悉的语法,但是当我有机会扩展我对Haskell的知识时,我会用它作为参考.(刚开始):) (2认同)