In Haskell, I want to read a file and then write to it. Do I need strictness annotation?

Posted by Steve on Stack Overflow See other posts from Stack Overflow or by Steve
Published on 2010-03-26T22:48:04Z Indexed on 2010/03/26 22:53 UTC
Read the original article Hit count: 351

Filed under:
|

Hi,

Still quite new to Haskell..

I want to read the contents of a file, do something with it possibly involving IO (using putStrLn for now) and then write new contents to the same file.

I came up with:

doit :: String -> IO ()
doit file = do
    contents <- withFile tagfile ReadMode $ \h -> hGetContents h
    putStrLn contents
    withFile tagfile WriteMode $ \h -> hPutStrLn h "new content"

However this doesn't work due to laziness. The file contents are not printed. I found this post which explains it well.

The solution proposed there is to include putStrLn within the withFile:

doit :: String -> IO ()
doit file = do
    withFile tagfile ReadMode $ \h -> do
        contents <- hGetContents h
        putStrLn contents
    withFile tagfile WriteMode $ \h -> hPutStrLn h "new content"

This works, but it's not what I want to do. The operation in I will eventually replace putStrLn might be long, I don't want to keep the file open the whole time. In general I just want to be able to get the file content out and then close it before working with that content.

The solution I came up with is the following:

doit :: String -> IO ()
doit file = do
    c <- newIORef ""
    withFile tagfile ReadMode $ \h -> do
        a <- hGetContents h
        writeIORef c $! a
    d <- readIORef c
    putStrLn d
    withFile tagfile WriteMode $ \h -> hPutStrLn h "Test"

However, I find this long and a bit obfuscated. I don't think I should need an IORef just to get a value out, but I needed "place" to put the file contents. Also, it still didn't work without the strictness annotation $! for writeIORef. I guess IORefs are not strict by nature?

Can anyone recommend a better, shorter way to do this while keeping my desired semantics?

Thanks!

© Stack Overflow or respective owner

Related posts about haskell

Related posts about haskell-io