ディレクトリ内の各画像ファイルに対して 1 つのコマンドを含むシェル スクリプトを作成するプログラムを作成しています。ディレクトリには 667,944 個の画像があるため、厳密性と遅延性の問題を適切に処理する必要があります。
これが私に与える簡単な例ですStack space overflow
。を使用してより多くのスペースを与えると機能しますが、ほとんどのメモリで実行でき+RTS -Ksize -RTS
、すぐに出力を生成できるはずです。だから、私は Haskell wiki と Haskell の wikibook で厳密性に関するものを読んで、問題を解決する方法を見つけようとしました。それは私を悲しませている mapM コマンドの 1 つであると思いますが、まだ解決していません。問題を分類するための厳密さについて十分に理解していません。
関連すると思われる SO に関するその他の質問をいくつか見つけました ( Is mapM in Haskell strict? Why does this program get a stack overload? and Is Haskell's mapM not lazy? )、しかし啓発はまだ私を逃れています。
import System.Environment (getArgs)
import System.Directory (getDirectoryContents)
genCommand :: FilePath -> FilePath -> FilePath -> IO String
genCommand indir outdir file = do
let infile = indir ++ '/':file
let angle = 0 -- have to actually read the file to calculate this for real
let outfile = outdir ++ '/':file
return $! "convert " ++ infile ++ " -rotate " ++ show angle ++
" -crop 143x143+140+140 " ++ outfile
main :: IO ()
main = do
putStrLn "#!/bin/sh"
(indir:outdir:_) <- getArgs
files <- getDirectoryContents indir
let imageFiles = filter (`notElem` [".", ".."]) files
commands <- mapM (genCommand indir outdir) imageFiles
mapM_ putStrLn commands
編集:テスト #1
これがサンプルの最新バージョンです。
import System.Environment (getArgs)
import System.Directory (getDirectoryContents)
import Control.Monad ((>=>))
genCommand :: FilePath -> FilePath -> FilePath -> IO String
genCommand indir outdir file = do
let infile = indir ++ '/':file
let angle = 0 -- have to actually read the file to calculate this for real
let outfile = outdir ++ '/':file
return $! "convert " ++ infile ++ " -rotate " ++ show angle ++
" -crop 143x143+140+140 " ++ outfile
main :: IO ()
main = do
putStrLn "TEST 1"
(indir:outdir:_) <- getArgs
files <- getDirectoryContents indir
putStrLn $ show (length files)
let imageFiles = filter (`notElem` [".", ".."]) files
-- mapM_ (genCommand indir outdir >=> putStrLn) imageFiles
mapM_ (\filename -> genCommand indir outdir filename >>= putStrLn) imageFiles
コマンドでコンパイルしますghc --make -O2 amy2.hs -rtsopts
。コマンド./amy2 ~/nosync/GalaxyZoo/table2/images/ wombat
で実行すると、次のようになります
TEST 1
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.
代わりにコマンド./amy2 ~/nosync/GalaxyZoo/table2/images/ wombat +RTS -K20M
で実行すると、正しい出力が得られます...最終的には:
TEST 1
667946
convert /home/amy/nosync/GalaxyZoo/table2/images//587736546846572812.jpeg -rotate 0 -crop 143x143+140+140 wombat/587736546846572812.jpeg
convert /home/amy/nosync/GalaxyZoo/table2/images//587736542558617814.jpeg -rotate 0 -crop 143x143+140+140 wombat/587736542558617814.jpeg
...等々。