STArrayで最小要素を見つけようとする次の試みが、ghc
(-Oレベルに関係なく、7.4.1)でコンパイルされたときにスタックスペースのオーバーフローにつながる理由を理解するのに苦労していますが、次の場合は正常に機能しますghci
:
import Control.Monad
import Control.Monad.ST
import Control.Applicative
import Data.Array.ST
n = 1000 :: Int
minElem = runST $ do
arr <- newArray ((1,1),(n,n)) 0 :: ST s (STArray s (Int,Int) Int)
let ixs = [(i,j) | i <- [1..n], j <- [1..n]]
forM_ ixs $ \(i,j) -> writeArray arr (i,j) (i*j `mod` 7927)
-- readArray arr (34,56) -- this works OK
-- findMin1 arr -- stackoverflows when compiled
findMin2 arr -- stackoverflows when compiled
findMin1 arr = do
es <- getElems arr
return $ minimum es
findMin2 arr = do
e11 <- readArray arr (1,1)
foldM (\m ij -> min m <$> readArray arr ij) e11 ixs
where ixs = [(i,j) | i <- [1..n], j <- [1..n]]
main = print minElem
注:切り替えてSTUArray
もST.Lazy
効果がないようです。
STArray
しかし、主な質問:内部でこのような「折り畳みのような」操作を大規模に実装する適切な方法は何でしょうST
か。