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

后端 未结 4 1323
予麋鹿
予麋鹿 2021-02-07 09:14

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 th

4条回答
  •  渐次进展
    2021-02-07 09:26

    The reason your first program does not work is that withFile closes the file after executing the IO action passed to it. In your case, the IO action is hGetContents which does not read the file right away, but only as its contents are demanded. By the time you try to print the file's contents, withFile has already closed the file, so the read fails (silently).

    You can fix this issue by not reinventing the wheel and simply using readFile and writeFile:

    doit file = do
        contents <- readFile file
        putStrLn contents
        writeFile file "new content"
    

    But suppose you want the new content to depend on the old content. Then you cannot, generally, simply do

    doit file = do
        contents <- readFile file
        writeFile file $ process contents
    

    because the writeFile may affect what the readFile returns (remember, it has not actually read the file yet). Or, depending on your operating system, you might not be able to open the same file for reading and writing on two separate handles. The simple but ugly workaround is

    doit file = do
        contents <- readFile file
        length contents `seq` (writeFile file $ process contents)
    

    which will force readFile to read the entire file and close it before the writeFile action can begin.

提交回复
热议问题