SICP : 3.1.2 : Concurrent Clean : モンテカルロ法 : 一意型の扱いについて
[id:lethevert:20060202:p1]で一意型の考察を行っていたが、それに関連する。
モンテカルロ法でPIを推定するという例題。
import StdEnv, OptEnv mapU :: [(.f -> (a, .f))] .f -> ([a], .f) mapU [] f = ([], f) mapU [x:xs] f # (a, f) = x f # (as, f) = mapU xs f = ([a:as], f) monte_carlo :: Int a -> [a] monte_carlo 0 a = [] monte_carlo trials a = [a:monte_carlo (trials-1) a] cesaro_test r # (r1, r) = nextRand r # (r2, r) = nextRand r = (1 == gcd r1 r2, r) estimate_pi trials # r = mkRandomInt # (rs, r) = mapU (monte_carlo trials cesaro_test) r # frac = (\x y = toReal x / toReal y) $$ foldr (\b (x,y) = (if b (x+1) x, y+1)) (0,0) rs = sqrt (6.0 / frac) Start = estimate_pi 1000
monte_carlo関数は、repeatn関数で十分なのだが、問題との対比を分かりやすくしたかったので関数を新たに作成した。
mapUで一意型を高階的に扱えるようにしているのが味噌なのだが、一意型が邪魔をして遅延評価が有効にならない。そのため、小さいヒープサイズしか許可していないと、すぐにHeap Fullになってしまう。
上手く遅延評価を有効にしたまま、高階的なプログラミングはできないものか。