mohammad
mohammad

Reputation: 100

Read a text file in Haskell and process each line of that separately

How can I write a code with Haskell language containing following details:

Note: Lines are separated and organized in input file previously, and are ready for processing.

Here there is my code for what I mean about above details. Indeed I want you guide me about ? part in the code below, and help me to complete ? part in this code according to what I mentioned in comment --/ part.

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*

Thanks for your answers.

EDIT 1:

I tried to construct a loop in my code and I wrote the following code:

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*

But steel I have problems when I try to compile it, and I catch an error which I can't fix it: parse error in pattern: loop I hope you help me to solve this problem.

Upvotes: 4

Views: 3935

Answers (1)

bheklilr
bheklilr

Reputation: 54058

I would recommend separating our the input, the processing, and the output into separate functions. In particular, this gives the advantage that all your data processing is pure rather than mixing the processing and file IO (this is known as separation of concerns):

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"

Inside processData you could do something like

processData :: PGF -> String -> String
processData gr content
    = unlines
    $ map (processLine gr)
    $ lines content
    where
        processLine :: PGF -> String -> String
        processLine pgf line = ???

The lines function will split a string into lines, then you process each using processLine, then use unlines to join it back into a single string ready for output.

Upvotes: 4

Related Questions