Haskell:逐行读取文件并放入列表中

时间:2014-03-20 23:40:54

标签: haskell readfile nested-lists

我正在尝试将文件名放入我的程序中,然后逐行读取文件到字符串列表中。我希望在进入程序的其余部分之前读取整个文件。我试图阅读的文件也是大约10K行。我还需要检查每行的长度,以便能够将它们放入不同的列表中。我目前有:

stageone :: String->[[String]]
stageone xs = do
        fileLines <-readFile.xs
        let line = lines fileLines
        xss -- dont know where to go from here

3 个答案:

答案 0 :(得分:10)

严格阅读文件的一种简单方法是使用Text,默认情况下严格readFile

import qualified Data.Text    as Text
import qualified Data.Text.IO as Text

main = do
    ls <- fmap Text.lines (Text.readFile "filename.txt")
    ... -- The world is your oyster!

通过程序的第二行,整个文件已经处理完毕。

学习使用Text代替String是一个好习惯,因为Text更有效率。要详细了解text库,您可以开始here

答案 1 :(得分:1)

欢迎来到Haskell。不幸的是,你的函数类型签名不起作用。你不能在这里离开IO monad。

stageone :: String -> IO [[String]]

是你最终会得到的。

您要做的是将您的需求分解为功能并实现每个功能。这些函数可能是没有IO的纯函数。然后回来把它们放在一起。这就是Haskell代码的开发方式。注意类型签名。如果你感到难过,试着写下签名并从那里开始工作。

如何确定线的长度?

如何将函数应用于列表中的每个项目并保留结果?

如何从文件中读取一行?

一旦你有10K线长,那么什么?把它们写出来?打印出来?

制定计划后,您可以在ghci中编写和测试这些较小的部分。

祝你好运。

答案 2 :(得分:1)

好的,这是所有无点的一线荣耀(或丑陋)中的函数,看不到一个lambda ......

module Main where

import Data.List ( sortBy, groupBy )
import Data.Function ( on )
import Data.Ord ( comparing )
import Control.Arrow ( (&&&) )

stageone :: String -> IO [[String]]
stageone = fmap (map (map snd) . groupBy ((==) `on` fst) . sortBy (comparing fst) . map (length &&& id) . lines) . readFile

让我们打破它。顶级是readFilefmap的组合。我们总是从右到左阅读功能构成。 stageone的无点参数传递给readFileIO String返回fmap String发送其函数参数以转换IO内的lines {1}}糖果壳。

这个功能是我们从右到左阅读的另一个作品。首先,我们将String应用于map,将其分解为一系列行。然后我们在行列表上(length &&& id) groupBy,将每行转换为由行的长度和行本身组成的对。接下来,我们通过比较每个(长度)的第一个元素对对列表进行排序。排序是稳定的,因此线条将在相同长度线的运行中保持其原始顺序。接下来,我们将((==) `on` fst)应用于map (map snd)map将具有相同第一个元素(长度)的对的运行分组到他们自己的子列表中。最后,我们将map应用于对列表列表。外部{{1}}遍历组,内部{{1}}遍历组内对的列表,用第二个元素(行)替换每对。

呼!