Reddit でいくつかのコードについて話し合っていたのですが、これが io-streams でどのように実装されるのかに興味を持ちました。ディレクトリ構造をトラバースし、すべてのファイル名を出力する次のコードを検討してください。
import Control.Exception (bracket)
import qualified Data.Foldable as F
import Data.Streaming.Filesystem (closeDirStream, openDirStream,
readDirStream)
import System.Environment (getArgs)
import System.FilePath ((</>))
printFiles :: FilePath -> IO ()
printFiles dir = bracket
(openDirStream dir)
closeDirStream
loop
where
loop ds = do
mfp <- readDirStream ds
F.forM_ mfp $ \fp' -> do
let fp = dir </> fp'
ftype <- getFileType fp
case ftype of
FTFile -> putStrLn fp
FTFileSym -> putStrLn fp
FTDirectory -> printFiles fp
_ -> return ()
loop ds
main :: IO ()
main = getArgs >>= mapM_ printFiles
単純にファイルを印刷する代わりに、ある種のストリーミング ファイルパス表現を作成したいとします。これが列挙子、コンジット、およびパイプでどのように機能するかを知っています。ただし、中間ステップでは希少なリソース ( DirStream
) を取得する必要があるため、io-stream の実装がどのようになるかはわかりません。誰かがそれがどのように行われるかの例を提供できますか?
比較のために、 と を介して可能になったコンジットの実装を次に示します。上記と同じファイル印刷プログラムを実装するためにコンジット コードを使用する方法を次に示します。bracketP
MonadResource
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Resource (runResourceT)
import Data.Conduit (($$))
import Data.Conduit.Filesystem (sourceDirectoryDeep)
import qualified Data.Conduit.List as CL
import System.Environment (getArgs)
main :: IO ()
main =
getArgs >>= runResourceT . mapM_ eachRoot
where
-- False means don't traverse dir symlinks
eachRoot root = sourceDirectoryDeep False root
$$ CL.mapM_ (liftIO . putStrLn)