7

Word32、String (カリー化は無視) などのいくつかのパラメーターを取り、IO Word32 を出力する関数を haskell で作成しました。さて、これは真の意味での関数です:同じ入力に対して、出力は常に同じになります. 副作用はありません。関数が Word32 ではなく IO Word32 を返す理由は、関数が多くの 32 ビット リニア フィードバック シフト レジスタ (lfsr) およびその他のレジスタをループ内で数回更新して、最終的な Word32 出力を計算するためです。

私の質問は次のとおりです。この関数には実質的に副作用がないことを考えると、関数がIO Word32ではなくWord32を返すように、関数実装内でこれらのレジスタ更新を非表示にすることは可能ですか? もしそうなら、どのように?

4

3 に答える 3

13

はい!Haskell はこれを行うことができます。

STモナド

関数の外側のオブザーバーから完全に隠されている可変状態 (レジスター) を実際に使用する場合、メモリー効果のみのモナドである ST モナドにいます。経由で ST の世界に入り、runST機能を終了すると、すべての効果が表示されないことが保証されます。

これは、ローカルで変更可能な状態を操作するための正確な計算環境です。

純粋に機能的な状態: State モナド

ただし、実際にレジスタやセルを変更するのではなく、純粋に機能的な値を何度も更新する場合は、より単純な環境を利用できます: State モナドです。これは変更可能な状態を許可しませんが、ローカル状態の錯覚を与えます。

IO、および unsafePerformIO

最後に、モナドのようにローカルで変更可能な効果STがあるが、何らかの理由でその状態で (FFI 呼び出しなどを介して) IO 操作が必要になる場合、STモナドをほぼ同じようにシミュレートできます。unsafePerformIOの代わりに を使用runSTしてローカル IO 環境を導入することにより、安全性が大幅に向上します。IO モナドには抽象化を強制するナイス型がないため、副作用が観察できないことを手動で確認する必要があります。

于 2011-05-20T15:38:59.553 に答える
5

FFIを使用してその関数をインポートした場合はIO、リターンタイプからを削除するだけです。それ以外の場合は、から使用unsafePerformIO :: IO a -> aSystem.IO.Unsafeます。この関数はHaskellで最も危険な関数の1つであることに注意してください。結果について本当に確信が持てない場合は、それを使用しないでください。しかし、あなたの目的のために、それは大丈夫のようです。

于 2011-05-20T15:37:03.803 に答える
3

はい、これは unsafePerformIO の正当な使用です。ただし、目に見える影響がないと本当に確信している場合にのみ問題ありません。

于 2011-05-20T15:38:04.093 に答える