内包表記で生成したリストを2回使うと、スペースリークでシステムが停止してしまう
円周率を近似するコードです。
main :: IO ()
main = do
let points = [(x,y) | x<-range 10000, y<-range 10000]
let all = length $ points
let hit = length $ filter ((<= 1) . distance) points
putStrLn $ show $ (fromIntegral hit * 4) / (fromIntegral all)
where
range n = (map (/ n) [0 .. n])
distance (a,b) = sqrt(a*a+b*b)
このコードを実行するとメモリが大量に消費され、システムが停止します。何か問題があるようです。
しかし、hit だけを評価、あるいは all だけを評価すると、このコードは動作します。
main :: IO ()
main = do
let points = [(x,y) | x<-range 10000, y<-range 10000]
let all = length $ points
let hit = length $ filter ((<= 1) . distance) points
putStrLn $ show hit
--putStrLn $ show all -- このコメントアウトを外して hit と all 両方を表示しようとするとスペースリークが発生する
where
range n = (map (/ n) [0 .. n])
distance (a,b) = sqrt(a*a+b*b)
これは何が起きているのでしょうか?