2016-05-12 20 views
3

私はほぼ純粋な数学的計算のプログラムを持っています。問題は、それらの計算の一部がモンテカルロ生成値で動作することです。私は2つの設計オプションを持っているようランダム値を計算するhaskellプログラムでモナドを構造化する方法は?

それはそうです:

どちらのすべての私の計算機能は、事前に生成されたモンテカルロチェーンが含まれている追加のパラメータを取ります。これにより私はどこでも純粋な関数を保つことができますが、他の関数を呼び出す関数があるので、コードベースに多くのラインノイズが追加されます。

他のオプションは、すべての計算機能をモナドにすることです。関数の中には、ランダム値を必要とする関数を呼び出す関数を呼び出しているランダム値を使用していないものもあるので、これは残念です。

ここに好適な設計に関するいかなるガイダンスはありますか?具体的には、モンテカルロ値が関係するコード内のモナド/非モナド関数の分離?

+1

次の関数に転送する必要がある各ステップで新しい値を作成していますか、複数の関数で1つの値しか使用していませんか?前者の場合は国家モナドが良い選択ですが、後者ならリーダーモナドがおそらく最良の選択肢です。あなたは実際に 'MonadReader'を使って関数を書くことができますし、後でそれらを純関数として使うことができます。 – bheklilr

+0

これは、あらかじめ計算された文脈を回るのと似ているでしょうか?純粋に私がリストの周りを回っていた場合を除いて、リストはリーダーか州に置き換えられますか? – daj

+0

関数のいくつかがランダム値を使用していない場合、すべての関数にparamを追加するか、すべてをモナドアクションに変換することは、唯一の選択肢にはなりません。ランダム性/非決定性を必要としないfnを変更しないでください。あなたはあなたのモナド/ファンクターの上でそれらを常にfmapしたり、モナドの 'let'式でそれらを使うことができます。ランダム性を必要とするアクションの場合、 'MonadReader StdGen m'制約を持つモナドにそれらを保存させるか、それらのfnを純粋なままにして、古い世代のものを得るために' StdGen'パラメータを 'split'与えます。 – liminalisht

答えて

2

他のオプションは、すべての計算機能をモナドにすることです。関数の中には、ランダム値を必要とする関数を呼び出す関数を呼び出しているランダム値を使用していないものもあるので、これは残念です。

私はこのアプローチに従うことをお勧めしますが、私はあなたの評価で「不運」であると意見を異ならせています。どのモナドがであり、正確にはで、あなたの純粋なコードとあなたの副作用コードが分離しています。あなたの純粋な関数は純粋な型を持つことができ、Functor/Applicative/Monadのメソッドは、ランダム生成パーツと「結びつける」役割を果たします。標準的な操作の署名に瞑想(ここではいくつかの理想的なRandomモナドのタイプに特化した):

-- Apply a pure function to a randomly selected value. 
fmap :: (a -> b) -> Random a -> Random b 

-- Apply a randomly selected function to a randomly selected argument. 
-- The two random choices are independent. 
(<*>) :: Random (a -> b) -> Random a -> Random b 

-- Apply a two-argument function to a randomly selected arguments. 
-- The two random choices are independent. 
liftA2 :: (a -> b -> c) -> Random a -> Random b -> Random c 

-- Make a `Random b` choice whose distribution depends on the value 
-- sampled from the `Random a`. 
(>>=) :: Random a -> (a -> Random b) -> Random b 

だからあなたのアプローチの再公式バージョンは次のとおりです。どこのことができます

  • 、純粋な関数を書きます。
  • Functor/Applicative/Monadクラスの操作を使用してランダムな値で動作するようにこれらの純粋な機能を調整します。
  • タイプがRandomであると言われている箇所があれば、それらのクラスの操作(またはそのために存在する豊富なユーティリティ関数)を使ってRandomの部分をどのように因数分解するかを理解してください。

これは乱数生成に固有のものではなく、のいずれかのモナドに適用されます。

あなたはこの記事を読んで楽しむかもしれない、と著者のランダム生成モナドライブラリをチェックアウトする場合があります:

私はあなたが記事のアプローチを実行する必要があり疑いますモデル化のために自由なモナドを使用するのですが、確率分布モナドに関する概念的なビットはおそらくいくつかの助けになるでしょう。

+0

ポインタありがとう。私は意図的に無料のモナドを避けてきました。なぜなら私は最初にバニラのモナドを内面化したいからです。 jaredはいくつかクールなことをしているようだ。そして、私はhaskellコミュニティで数値/科学的コンピューティングをやる人が増えたかったと思う。 「残念なことに」は、作成が簡単ではないモナドでないコードを見つける初心者のビューを指します。もっと練習すれば、より深い練習で訓練の恩恵を理解するようになるだろうが、慣れていくことがある。 – daj

+0

@daj:もう一度、この記事の恩恵を受けるために無料のモナドを掘り下げて調べる必要があると私は思っています。 RNGモナドライブラリーを効果的に使用する方法を学ぶことに、あなたの「一度に一度」の態度が必要です。 –

0

TL; DR: 抽象的なランダム関数発生器に検討し、それを引数として渡します。 Haskellの型クラスは、できるだけその抽象を隠すのに役立ちます。

残念ながら、ここに特効薬はありません。あなたが副作用を使用しているので、あなたの "関数"は単に適切な意味での関数ではありません。ハスケルは、あなたがその事実を隠すことを許さない(安全保証の最大部分を占める)。だから何らかの形でこの事実を表現する必要があります。また、モナド演算と(平易な)関数の違いを混同しているように見えます。(間接的に)ランダム値を使用する関数は、暗黙的にモナドです。モナド以外の関数は、モナド演算の中で常に使用できます。だから、おそらく真に非モナド的な関数をそのまま実装し、それがどれくらい遠くにあるのかを知るべきです。

まったく無関係な注釈:怠惰が必須ではなく、Haskellの強力な安全性があなたに負担をかけすぎていても、(大部分の)機能コードを書きたい場合は、OCamlに試してみてくださいMLの他の方言)。

関連する問題