LoginSignup
1
1

More than 5 years have passed since last update.

withFileの使いどころではまった時のメモ

Last updated at Posted at 2015-02-26

学習の素材は、
すごいHaskellたのしく学ぼう!

この表記は、私見・感想です。

期待するファイル読み込みができない

文字列を読み込むためだけのIOアクションを引数にとった withFile を使ってはいけない。その後にputStrLn , writeFile などで取得した文字列を参照しようとしても、空文字になってしまう。

例えばこのようなケース。

入力ファイル
$ cat baabaa.txt 
Baa, baa, black sheep,
Have you any wool?
Yes, sir, yes, sir
Three bags full;
$
サンプルコード
import System.IO
main = do
    str <- readFile'' "baabaa.txt"
    writeFile   "output.txt" str -- (*1)読み込んだ文字列をファイルに書き出す

readFile'' :: FilePath -> IO String
readFile'' name = withFile name ReadMode hGetContents

このプログラムを起動すると output.txt には何の文字列も入っておらず、これは期待通りではない。

出力ファイル
$ cat  output.txt 
$ 

これは、次の要因で起こってしまう。

  • withFile は、関数の終了とともにファイルハンドルを閉じてしまう
  • 遅延IOなので、必要になるまで( putStrLnなどが呼び出されるまで ) withFile の結果は評価されない

このため、必要になった時にはハンドルが閉じていて期待していた文字列を評価できず、IOアクションの結果が"" となってしまう。

なお次のプログラムでも、同じように文字列を取得できなかった。

import System.IO

main = do
    handle <- openFile "baabaa.txt" ReadMode
    contents <- hGetContents handle
    hClose handle
    putStrLn contents

ハンドルが閉じている状態でcontents に関数を適用しても、エラーとはならないようだ。また、途中でlet a = contents などと変数にバインドしても、浅いコピーしかされていない様子だった。

参考サイト

http://stackoverflow.com/questions/9406463/withfile-vs-openfile
http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO.html#v:withFile

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1