It's me again:). I try to write a program which copies lines which number is divisible by 5 to another file. Here is code (sorry for Polish names):
import IO
przepiszConHelper :: Handle -> Handle -> Integer -> Integer -> IO ()
przepiszConHelper wejscie wyjscie liczba licznik = do
eof <- hIsEOF wejscie
if eof then return ()
else
linia <- hGetLine wejscie
if (mod licznik liczba) == 0 then
hPutStrLn wyjscie linia
przepiszConHelper wejscie wyjscie liczba (licznik + 1)
przepiszCon :: String -> String -> Integer -> IO ()
przepiszCon wejscie wyjscie liczba = do
wej <- openFile wejscie ReadMode
wyj <- openFile wyjscie WriteMode
przepiszConHelper wej wyj liczba 0
hClose wej
hClose wyj
main = przepiszCoN "wejscie.txt" "wyjscie.txt" 5
I think it should works... but I get one, strange error:
przepisz.hs:6:9:
Parse error in pattern: if eof then return () else linia
Which makes no sense for me. I had been using the same expression in another programs and it worked like a harm. I tried to remove these lines and write them with different indentations (I remember that I had some issues with white-spaces before). But I still get the same error:(.
--edit
OK, I have first error... it's just else do
instead of else
. But here comes another problem:
przepisz.hs:11:25: parse error on input `przepiszConHelper'
The problem is here:
if eof then return ()
else
linia <- hGetLine wejscie
Indeed, the problem is not whitespace--your issue is that you seem to expect a do
block to extend inside subexpressions, which is not the case. The else
clause needs to define its own do
block:
if eof then return ()
else do
linia <- hGetLine wejscie
There's another error after that, however:
if (mod licznik liczba) == 0 then
hPutStrLn wyjscie linia
przepiszConHelper wejscie wyjscie liczba (licznik + 1)
You're missing an else
clause for this if
. if
is always an expression in Haskell, so it must always evaluate to something. If you want to express "do this IO
action if the condition is true, otherwise do nothing" you can use return ()
:
if (mod licznik liczba) == 0
then hPutStrLn wyjscie linia
else return ()
The standard library even includes the function when
to express this idea:
when (mod licznik liczba == 0) $ hPutStrLn wyjscie linia
If you wanted, you could rewrite the outer if
expression the same way, and get something like this:
przepiszConHelper :: Handle -> Handle -> Integer -> Integer -> IO ()
przepiszConHelper wejscie wyjscie liczba licznik = do
eof <- hIsEOF wejscie
when (not eof) $ do
linia <- hGetLine wejscie
when (mod licznik liczba == 0) $ hPutStrLn wyjscie linia
przepiszConHelper wejscie wyjscie liczba (licznik + 1)