我正在尝试将文件名放入我的程序中,然后逐行读取文件到字符串列表中。我希望在进入程序的其余部分之前读取整个文件。我试图阅读的文件也是大约10K行。我还需要检查每行的长度,以便能够将它们放入不同的列表中。我目前有:
stageone :: String->[[String]]
stageone xs = do
fileLines <-readFile.xs
let line = lines fileLines
xss -- dont know where to go from here
答案 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
让我们打破它。顶级是readFile
和fmap
的组合。我们总是从右到左阅读功能构成。 stageone
的无点参数传递给readFile
,IO String
返回fmap
String
发送其函数参数以转换IO
内的lines
{1}}糖果壳。
这个功能是我们从右到左阅读的另一个作品。首先,我们将String
应用于map
,将其分解为一系列行。然后我们在行列表上(length &&& id)
groupBy
,将每行转换为由行的长度和行本身组成的对。接下来,我们通过比较每个(长度)的第一个元素对对列表进行排序。排序是稳定的,因此线条将在相同长度线的运行中保持其原始顺序。接下来,我们将((==) `on` fst)
应用于map (map snd)
,map
将具有相同第一个元素(长度)的对的运行分组到他们自己的子列表中。最后,我们将map
应用于对列表列表。外部{{1}}遍历组,内部{{1}}遍历组内对的列表,用第二个元素(行)替换每对。
呼!