私は100回ループする関数を記述しようとしています。このループではpriceJumpという関数を呼び出しています。ループが最初に開始されるとき、この関数のprice引数は100の初期値をとる。しかし、すべてのループの後で、関数はpriceJump関数に渡すべき新しい価格を生成する。ループ中に新しい値で関数を呼び出す
私はこのロジックをコード化しようとしましたが、失敗しました(以下のコード)。問題は、新しい価格を生成するコードがモナド的な方法で行われるため、値mの型がDoubleで、mが型クラスPrimMonadによって制約されていることです。
私はおそらく、私がこれらの問題を経験している理由である慣用的なハスケルでこれをやっていないので、正しい方向へのポインタがあればそれも分かります。要約すると、初期価格が引き渡された価格関数を呼び出すことであり、新しい価格が生成されるたびに新しい価格がその値に戻されるべきです。
import Control.Monad.State
import Control.Monad.Primitive
import System.Random.MWC
import System.Random.MWC.Distributions
priceJump :: Double -- price
-> Double -- rate
-> Double -- vol
-> Double -- ts
-> Double -- rnd
-> Double -- new price
priceJump price rate vol ts rnd = price * (1 + (rate * ts) + (vol * sqrt(ts) * rnd))
loop :: PrimMonad m => Gen (PrimState m) -> Int -> Double -> Double -> Double -> Double -> m Double
loop gen turns price rate vol ts
| turns <= 0 = (priceJump price rate vol ts) <$> (normal 0 1 gen)
| turns == 100 = (priceJump price rate vol ts) <$> (normal 0 1 gen)
| otherwise = loop gen (turns - 1) (priceJump price rate vol ts) <$> (normal 0 1 gen) rate vol ts
追記:これは、リストの素敵な使用であることが判明し、GHCは賢いことと、それは非常に効率的ですので、私のためにリストを離れてストリーミングするために表示されますが、コードが異なることを見終わっていません。 – jozefg
私はあなたの例をコンパイルすることができません。私は間違ったことをする必要があります。私はここにエラーメッセージを貼り付けました:http://lpaste.net/156961。私はあなたの2番目の例のように 'foldr'を使いたかったのですが、ランダムな値のリストを前もって生成する方法は決してできませんでした。 –
@ Mika'ilエラーはこのコードに関連していないようです - 彼らは 'priceJump'関数を指しているようです。しかし、それは私のためにうまくコンパイルされました。あなたのコードに追加された答えの中のどちらの関数も私のためにコンパイルされます。 @jozefg実際には、あなたが頼りにすることができる(まだ私はそうしていない)融合ルールを見つけたら、それはより簡単になりますが、 'foldr/replicate'と' foldr/sequence/replicate'は通常うまくいきます。 – user2407038