我正在编写一个程序,该程序创建一个 shell 脚本,其中包含一个用于目录中每个图像文件的命令。目录中有 667,944 张图片,所以我需要妥善处理严格/懒惰的问题。
这是一个简单的例子,它给了我Stack space overflow
。如果我给它更多空间使用它确实有效+RTS -Ksize -RTS
,但它应该能够以很少的内存运行,立即产生输出。因此,我一直在阅读 Haskell wiki 和有关 Haskell 的 wikibook 中有关严格性的内容,试图找出解决问题的方法,我认为这是让我感到悲伤的 mapM 命令之一,但我仍然没有对严格性的理解不够,无法对问题进行排序。
我在 SO 上发现了一些其他似乎相关的问题(Haskell 中的 mapM 是否严格?为什么这个程序会出现堆栈溢出?以及Haskell 的 mapM 不懒惰吗?),但启蒙仍然让我望而却步。
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.
如果我改为使用 command 运行它./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
...等等。