2014年2月12日水曜日

開発環境

Real World Haskell―実戦で学ぶ関数型言語プログラミング(Bryan O'Sullivan (著)、 John Goerzen (著)、 Don Stewart (著)、山下 伸夫 (翻訳)、伊東 勝利 (翻訳)、株式会社タイムインターメディア (翻訳)、オライリージャパン)の9章(入出力事例研究: ファイルシステム検索ライブラリ)、9.5(ファイルサイズを安全に決める)、9.5.1(獲得 - 使用 - 開放サイクル)の練習問題 1.を解いてみる。

その他参考書籍

練習問題 1.

そのままだと、次のようなエラーになるのでとりあえずコードを修正。

    No instance for (GHC.Exception.Exception e0)
      arising from a use of `handle'
    The type variable `e0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance GHC.Exception.Exception
                 Control.Exception.Base.NestedAtomically
        -- Defined in `Control.Exception.Base'
      instance GHC.Exception.Exception
                 Control.Exception.Base.NoMethodError
        -- Defined in `Control.Exception.Base'
      instance GHC.Exception.Exception
                 Control.Exception.Base.NonTermination
        -- Defined in `Control.Exception.Base'
      ...plus 7 others
    In the expression:
      handle (\ _ -> return Nothing) (return (Just 10))
    In an equation for `getFileSize':
        getFileSize path
          = handle (\ _ -> return Nothing) (return (Just 10))

コード(BBEdit, Emacs)

BetterPredicate.hs

{-# OPTIONS -Wall -Werror #-}

import Control.Exception (handle, bracket, SomeException)
import System.IO (IOMode(..), openFile, hClose, hFileSize)

getFileSize :: FilePath -> IO (Maybe Integer)
getFileSize path = handle nothing $
    bracket (openFile path ReadMode) hClose $ \h -> do
        size <- hFileSize h
        hClose h
        return (Just size)

nothing :: SomeException -> IO (Maybe Integer)
nothing _ = return Nothing

入出力結果(Terminal, インタプリタghci)

$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :load BetterPredicate.hs 
[1 of 1] Compiling Main             ( BetterPredicate.hs, interpreted )
Ok, modules loaded: Main.
*Main> getFileSize "BetterPredicate.hs"
Just 432
*Main> getFileSize "abcde"
Nothing
*Main> :quit 
Leaving GHCi.
$

bracketとhandleを呼ぶ順番は重要。逆の順序にすると、先に例外を取り除いてしまい、ゴミになったファイルをハンドルにたまったままにしてしまう。

0 コメント:

コメントを投稿