64

One thing that has always confused me is whether or not it's an okay time to use an IORef. Are there any guidelines that should be followed when deciding whether or not to use an IORef for a task? When is a good time to use the State monad over an IORef?

4

4 に答える 4

74

状態とそれに関連する ST はどちらも、ユニットとして実行できる「モノリシック」なステートフルな計算を生成します。それらは基本的に可変状態を結果を生成するために必要な中間データとして扱いますが、それ自体はプログラムの残りの部分にとって重要ではありません。

一方、IORef の内部に置くものは、実行される「計算」ではありません。これは、IO 内でかなり任意の方法で使用できる単純な値を保持する単なるボックスです。このボックスは、データ構造内に配置したり、プログラム (の IO 部分) に渡したり、都合の良いときにその内容を置き換えたり、関数によって閉じたりすることができます。 C のような言語のポインターは IORef でモデル化でき、どの言語でも C コードを記述できるという評判を維持したい専門の C プログラマーに大きな支援を提供します... これは間違いなく注意して使用する必要があるものです。

それでも、完全に不可能ではないにしても、コードの単一ブロック内の変更可能な状態の一部とのすべての相互作用を分離することは、時には非常に扱いにくいです。ボックスアプローチが唯一の選択肢かもしれません。Write Yourself a Scheme in 48 Hours チュートリアルの変更可能な状態を紹介する章 (ちなみに強くお勧めします) で例を示します(Scheme インタープリターの特定の設計において、Scheme 環境をモデル化するために、State や ST ではなく IORef を使用することが実際に最も適切である理由についての優れた議論については、リンクを参照してください。)

要するに、これらの環境は任意の方法でネストされ、ユーザー操作のインスタンス間で維持される必要があります ( (define x 1)Scheme REPL で入力された場合、ユーザーは後で入力しxて値として 1 を取得できるようになるはずです)、オブジェクト内に配置する必要があります。モデリング Scheme 関数 (Scheme 関数は作成された環境を閉じるため) など

要約すると、タスクがそれに適していると思われる場合、State は最もクリーンなソリューションを提供する傾向があると言えます。複数の個別の状態が必要な場合は、おそらく ST が役立ちます。ただし、ステートフルな計算が扱いにくいか、それ自体のコードに閉じ込めることが不可能である場合、状態は、複雑なプログラムの寿命の大部分の間、変更可能な形式で持続する必要があるなどの場合、IORefs はまさに適切なこと。

繰り返しになりますが、IO コードによって制御された方法で渡され、相互作用する可能性のある一種の可変状態が必要な場合は、STM とその TVars をチェックしてみてください! 並行性が存在する場合、それらははるかに優れており、実際、いくつかの並行性関連のタスクを実際に簡単に解決できます。ただし、これは質問とはあまり関係がないので、詳しく説明するのは控えます。:-)

于 2009-12-19T04:40:44.737 に答える
15

うーん。変更可能な状態が必要であるが、シングルスレッド環境にある場合は、IORef を使用します。または、同期変数によって保持される大きな構造内に可変フィールドが必要な場合。

一般に、MVar を使用します。それらはより堅牢なセマンティクスを持っています。

于 2009-12-19T04:15:21.073 に答える
3

個人的には、既に を使用している場合にのみIORefsを使用しても問題ないと思います。それ以外の場合は、 の優れたパフォーマンスが必要でない限り、常に. いくつかのヘルパー関数を使用して、モナドで状態の複数のスレッドを使用することができます。状態をタプルまたはレコードにし、各フィールドを個別に設定、取得、または更新する関数を定義するだけです。IOStateSTState

特に、通常、 を使用する意味はあまりありませんStateT s IO。既に をIO使用している場合は、既に変更可能な状態になっているので、それを使用することもできますReaderT (IORef s) IO。たとえば、.

于 2011-11-27T21:52:45.190 に答える
1

STRef状態がローカライズされていて、環境との対話を必要としない場合に使用します。

于 2009-12-19T04:14:17.223 に答える