在Haskell中读取文本文件并单独处理每一行

4
我该如何使用Haskell编写包含以下细节的代码:
  • 首先读取一个文本文件。
  • 然后,在循环中对该文本文件的每一行执行一个函数。
  • 最后将每个处理过的行写入输出文本文件。

注意:行在输入文件中已经分隔并组织好,准备好进行处理。

这是我的代码,它包含了上述细节。实际上,我希望您指导我下面代码中 ? 部分,并根据我在注释 --/ 部分中提到的内容帮助我完成 ? 部分。

main :: IO ()
main = do
 file:_ <- getArgs
 gr     <- readPGF file
 content <- readFile "input.txt"
 loop gr content


loop :: PGF -> String -> IO ()
loop gr content = ?
 -- ln <- lines content
 -- if ln == EndOfFile then putStrLn "bye" else do 
 -- appendFile "output.txt" $function gr line
 -- loop gr content

function :: PGF -> String -> String
function gr s = *functions body*

谢谢你的回答。 编辑1: 我尝试在我的代码中构建一个循环,我写了以下代码:
module Main where

import PGF
import System.Environment
import System.IO

main :: IO ()
main = do
 file:_ <- getArgs
 gr     <- readPGF file
 content <- readFile "testCasePF.txt"
 line <- lines content
 loop gr line


loop :: PGF -> String -> IO ()
loop g x:y = do    
 if x == "quit" then putStrLn "bye" else do
   appendFile "output.txt" $function g x      
   loop gr y

function :: PGF -> String -> String
function gr s = *function body*

但是当我尝试编译它时,我仍然遇到了问题,并且捕获了一个无法修复的错误: 模式中的语法错误:loop 我希望你能帮助我解决这个问题。


1
loop(gr content) 应该改为 loop gr content。函数应用时不需要使用括号,而在这里使用括号会导致类型错误,因为它让你看起来像是将参数 content 应用到函数 gr 上,这显然是不正确的。 - bheklilr
我想将内容作为参数传递到循环中,我只想将内容分隔成行,并在每行上应用翻译函数。你是正确的,我必须省略括号。 - mohammad
1个回答

4

我建议将输入、处理和输出分别放入不同的函数中。特别是,这样做的好处是所有数据处理都是纯粹的,而不是混合处理和文件IO(这被称为关注点分离):

readData :: FilePath -> IO (PGF, String)
readData file = do
    gr <- readPGF file
    content <- readFile "input.txt"
    return (gr, content)

processData :: PGF -> String -> String
processData gr content = undefined

outputData :: String -> IO ()
outputData contents = writeFile "output.txt" contents

main :: IO ()
main = do
    file:_ <- getArgs
    (gr, content) <- readData file
    outputData $ processData gr content
    putStrLn "bye"
-- Or simply
-- main = do
--     file:_ <- getArgs
--     readData file >>= outputData . processData . uncurry
--     putStrLn "bye"

processData 内部,您可以执行类似以下操作:
processData :: PGF -> String -> String
processData gr content
    = unlines
    $ map (processLine gr)
    $ lines content
    where
        processLine :: PGF -> String -> String
        processLine pgf line = ???
< p > lines 函数将字符串拆分为多行,然后您可以使用 processLine 处理每一行,最后使用 unlines 将其连接回一个准备好输出的单个字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接