s
は、ST
モナド内のオブジェクトがST
モナドの外側に漏れないようにします。
-- This is an error... but let's pretend for a moment...
let a = runST $ newSTRef (15 :: Int)
b = runST $ writeSTRef a 20
c = runST $ readSTRef a
in b `seq` c
さて、これはタイプエラーである(良いことです!私たちは、元の計算外に漏出するSTRef
をしたくありません!)。これは余分なs
のためにタイプエラーです。
runST :: (forall s . ST s a) -> a
これは、あなたが実行している計算上のs
が、それには何の制約を持たないために持っていることを意味しますrunST
が署名を持っていることを覚えておいてください。ですから、a
を評価しようとすると:s
はrunST
にforall
の外側を「エスケープ」しているので
a = runST (newSTRef (15 :: Int) :: forall s. ST s (STRef s Int))
結果が間違っているタイプSTRef s Int
を、持っているでしょう。型変数は常にforall
の内部に現れなければならず、Haskellは暗黙的にforall
個の量子を許しています。意味のある返り値の型をa
から把握できるようにするルールはありません。
別の例forall
で:あなたは物事がforall
を逃がすことができない理由を明確に示すために、ここでは単純な例である:それは戻ってくるので、
もちろん
f id
の
f :: (forall a. [a] -> b) -> Bool -> b
f g flag =
if flag
then g "abcd"
else g [1,2]
> :t f length
f length :: Bool -> Int
> :t f id
-- error --
は、エラーになりますブール値が真であるか偽であるかに応じて、Char
のリストまたはInt
のリストのいずれかです。 ST
の例のように、間違っているだけです。
一方、s
タイプのパラメータがない場合は、コードが明らかにかなり偽であるにもかかわらず、すべてがタイプチェックされます。 STは、実際にどのように動作する
:実装面を、ST
モナドは実際にIO
モナドとしてではなく、わずかに異なるインターフェイスと同じです。 ST
モナドを使用すると実際にunsafePerformIO
またはそれと同等のものが得られます。これを安全に実行できる理由は、すべてのST
関連の関数、特にforall
の部分の型シグネチャが原因です。
"ST monad"を検索すると、エントリがありますSTArraysに関する質問への副作用として私の疑問に答えます。ここで私の質問が重複しているかどうかは分かりません。 http://stackoverflow.com/questions/8197032/starray-documentation-for-newbies-and-state-st-related-questions – David
「はい」と答えるのはとても魅力的です。あなたの質問に。 :) – AndrewC
質問へのリンクを追加して、それを閉じると思います。これは将来的に簡単に検索し、b)いくつかの回答者を保存します。 – David