0

stepしたがって、基本的には、前の結果を取り込んで を出力する計算がありますRand g Path。ここPathで、 はカスタム データ型です (巡回セールスマンのような問題と考えてください)。MonadRandomジェネレーターの受け渡しなどすべてを処理させます。

たとえば、この計算自体の n 番目の構成を見つけたいと思います。今、私は使用しています

thecomputation :: (RandomGen g) => Rand g Path
thecomputation = (iterate (>>= step) (return startingPath)) !! n

そして、それを印刷するために実行します

main = do
  res <- evalRandIO thecomputation
  print res

しかし、私には問題があります

十分な高さを選択するnと (10^6 のオーダーが必要です)、スタック オーバーフローが発生します。

私は、計算が実際には重く構成された (ネストされた?) IO オブジェクトであるという事実に問題を追跡することができました。これは一連の IO 計算であるため、ghc はネストされた IO のすべてのレイヤーを追跡する必要があり、十分な数のレイヤーの後、あきらめます。

これにどう対処すればいいですか?命令型言語では、これにはあまり意味がありません。しかし、私はここで何をすべきですか?一部の IO を強制的に評価する必要がありますか、それとも ...?

このサイトには同様の質問がありますが、受け入れられた回答から役立つものを得ることができなかったので、まだかなり迷っています

具体例

import System.Random
import Control.Monad.Random
import Control.Monad

data Path = DoublePath Double deriving Show

step :: (RandomGen g) => Path -> Rand g Path
step (DoublePath x) = do
  dx <- getRandom
  return (DoublePath ((x + dx)/x))

thecomputation :: (RandomGen g) => Rand g Path
thecomputation = (iterate (>>= step) (return (DoublePath 10.0))) !! 1000000

main = do
  result <- evalRandIO thecomputation
  print result

コンピューターでオーバーフローする

4

2 に答える 2

2

型を厳密にするだけで十分です。これは、特に数値およびその他の「ボックス化できない」パラメーターの場合は第二の性質である必要があり、言語拡張は必要ありません。

data Path = DoublePath !Double deriving Show

 -- $ ghc -O2 doublepath.hs
 -- ...
 -- $ time ./doublepath
 -- DoublePath 1.526581416150007

 -- real    0m2.516s
 -- user    0m2.307s
 -- sys 0m0.092s
于 2013-05-14T20:15:17.913 に答える