haskell の stm ライブラリには、次の型シグネチャを持つ関数があります。
alwaysSucceeds :: STM a -> STM ()
Haskell の STM について私が理解していることから、STM 計算の実行中に何かが「うまくいかない」(その用語を大まかに使用すると) 3 つの方法があります。
- 読み取られた TVar の値は、別のスレッドによって変更されます。
- ユーザー指定の不変条件に違反しています。
retry
これは通常、最初からやり直すために呼び出すことによってトリガーされるようです。これにより、スレッドが効果的にブロックされ、読み取りセットの TVar が変更されると再試行されます。 - 例外がスローされます。呼び出し
throwSTM
が原因です。これは、トランザクションが再開されないため、最初の 2 つとは異なります。代わりに、エラーが伝播され、プログラムがクラッシュするか、IO モナドでキャッチされます。
これらが正確である場合 (正確でない場合は教えてください)、何ができるのか理解alwaysSucceeds
できません。そのalways
上に構築されているように見える関数は、次のように記述しなくてもよいようですalwaysSucceeds
。
--This is probably wrong
always :: STM Bool -> STM ()
always stmBool = stmBool >>= check
のドキュメントにalwaysSucceeds
は次のように書かれています:
alwaysSucceeds は、alwaysSucceeds に渡されたとき、現在のトランザクションの最後、および後続のすべてのトランザクションの最後に true でなければならない新しい不変条件を追加します。これらのポイントのいずれかで失敗した場合、違反しているトランザクションは中止され、不変条件によって発生した例外が伝播されます。
しかし、引数は型STM a
( では多態的a
) であるため、トランザクションが返す値を意思決定のどの部分にも使用することはできません。つまり、先ほど挙げたさまざまなタイプの障害を探しているようです。しかし、そのポイントは何ですか?STM モナドはすでに失敗を処理しています。この関数でラップすると、どのように影響しますか? また、型の変数がa
削除されて、結果が になるのはなぜSTM ()
ですか?