読者です 読者をやめる 読者になる 読者になる

Haskellプログラミングのはまりどころ

始めてHaskellプログラミングしたとき,すごく苦労したはずなのだが,
それがどういうところで,どのようにハマったかをもう忘れている.

IO モナドにハマってますヽ(  ̄д ̄;)ノ - 女子高生ぷろぐらまーなお☆のブログ
は多分こういうことをやろうとしたんじゃないかなぁ.と思う.
コメントにコードを貼ると読めなくなっちゃうんで,ここに書きます.

module Main where

import System.Time
import Data.List
import System.Directory

data Entry = Entry { path      :: FilePath
                   , timestamp :: ClockTime
                   , title     :: String
                   , body      :: [String]
                   }

getFileEntry :: FilePath -> IO Entry
getFileEntry f
 = do { mtime <- getModificationTime f
      ; cs    <- readFile f
      ; case unlines cs of
          (t,bs) -> return $ Entry { path      = f
                                   , title     = t
                                   , timestamp = mtime
                                   , body      = bs
                                   }
      }

getTextFileEntries :: FilePath -> IO [Entry]
getTextFileEntries d 
 =  do { setCurrentDirectory d 
       ; fs <- getDirectoryContents "."
       ; es <- mapM getFileEntry $ filter (isSuffixOf ".txt") fs
       ; setCurrentDirectory ".."
       ; return es
       }

main :: IO ()
main = mapM_ (putStrLn .  title) =<< getTextFileEntries "data"

(2007-10-23): 追記
上のコードは,IOエラーが発生した(getModificationTimeやsetCurrentDirectoryで指定したファイルやディレクトリが存在しないときに発生する)場合のエラー処理を何もおこなっていないことに注意してください.

ああ.エラー処理以外にも,はずかしいミスもある.getTextFileEntries の中で setCurrentDirectory で指定されたディレクトリに現在のディレクトリを移して処理を行い,getCurrentDirectory で元のディレクトリに戻るつもりの定義にしてるつもりで,移動先のディレクトリがこのプログラム起動時の現在のディレクトリの直下にあることを暗黙で仮定してしまっている.それで,getCurrentDirectory ".." で元の戻った積りになっている.

ダメ杉.

getTextFileEntries d 
 =  do { cdir <- getCurrentDirectory 
       ; setCurrentDirectory d 
       ; fs <- getDirectoryContents "."
       ; es <- mapM getFileEntry $ filter (isSuffixOf ".txt") fs
       ; setCurrentDirectory cdir
       ; return es
       }

としないと...自戒のためにミスはミスとしてそのまま記録しておきます.