2014年2月17日月曜日

開発環境

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

その他参考書籍

練習問題 1.

以下のコードじゃなくて、こちらのコードかも。

コード(BBEdit, Emacs)

FoldDir.hs

{-# OPTIONS -Wall -Werror #-}
module FoldDir where

import ControlledVisit (Info(..), getInfo, isDirectory, getUsefulContents)
import System.FilePath ((</>), takeExtension, takeFileName)
    
data Iterate seed = Done {unwrap :: seed}
                  | Skip {unwrap :: seed}
                  | Continue {unwrap :: seed}
                  deriving (Show)

type Iterator seed = seed -> Info -> Iterate seed

main :: IO ()
main = do
    paths1 <- foldTree id hs [] "."
    paths2 <- foldTree reverse hs [] "."
    putStrLn "id------------------"
    mapM_ putStrLn $ map takeFileName paths1
    putStrLn "reverse-------------"
    mapM_ putStrLn $ map takeFileName paths2

foldTree :: ([FilePath] -> [FilePath]) -> Iterator a -> a -> FilePath -> IO a
foldTree order iter initSeed path = do
    endSeed <- fold initSeed path
    return (unwrap endSeed)
        where fold seed subpath = do
                  contents <- getUsefulContents subpath
                  walk seed (order contents)
              walk seed (name:names) = do
                  let path' = path </> name
                  info <- getInfo path'
                  case iter seed info of
                       done@(Done _) -> return done
                       Skip seed' -> walk seed' names
                       Continue seed'
                           | isDirectory info -> do
                               next <- fold seed' path'
                               case next of
                                    done@(Done _) -> return done
                                    seed'' -> walk (unwrap seed'') names
                           | otherwise -> walk seed' names
              walk seed _ = return (Continue seed)

hs :: Iterator [FilePath]
hs paths info
    | takeExtension path == ".hs" = Continue (path:paths)
    | otherwise = Continue paths
    where path = infoPath info

入出力結果(Terminal, runghc)

$ runghc FoldDir.hs 
id------------------
temp.hs
temp.hs
FoldDir.hs
ControlledVisit.hs
BetterPredicate.hs
reverse-------------
BetterPredicate.hs
ControlledVisit.hs
FoldDir.hs
temp.hs
temp.hs
$

0 コメント:

コメントを投稿