なぜST
は次のコードを許可しないように設計されていますas shown in the wikibook?この記事では、ST
のエフェクトが別のST
に漏れることが示唆されていますが、なぜそれは本当に理解できません。ST参照は透過的ですか?
私は特定のST s (STRef s a)
を実行できないようです。 ST
エフェクトは含まれていますが、参照は透過的ですが、そのような使用は無効と見なされますか?
直観は1 IO
、多くの独立したST
があることに関連IO
とST
の意味の違いがあることを私に語ったが、私はよく分かりません。
> runST (newSTRef True)
<interactive>:5:8: error:
• Couldn't match type ‘a’ with ‘STRef s Bool’
because type variable ‘s’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
forall s. ST s a
at <interactive>:5:1-21
Expected type: ST s a
Actual type: ST s (STRef s Bool)
• In the first argument of ‘runST’, namely ‘(newSTRef True)’
In the expression: runST (newSTRef True)
In an equation for ‘it’: it = runST (newSTRef True)
• Relevant bindings include it :: a (bound at <interactive>:5:1)
> :t newSTRef
newSTRef :: a -> ST s (STRef s a)
> :t runST
runST :: (forall s. ST s a) -> a
「ST」の私の理解は、それは宇宙のように考える。すべての「ST」操作は、ある宇宙を別の宇宙に変えるかもしれない(突然変異による)。そのため、 'ST'は' RealWorld'でタグ付けすることで 'IO'に変えることができます。だからあなたの質問は本当に 'IO'が純粋かどうかを尋ねるのと同じです。 – HuStmpHrrr
'forall sのタイプのすべての値。 'IO A '型のすべての値は、(そのような値は値そのものではなく結果の値をどのように生成するかを表す計算であるため)参照透過的です。 'ST s(STRef s A)'は '実行 'できませんが、有効な計算です。例えば'STRef s A - > ST s B'型の関数を適用して' forall s 'を得ることができます。 ST s B 'を実行することができる。しかし、私は実際に何が問題なのか、なぜ問題のコードが許されるべきだと思いますか? (注:「私は本当になぜか分かりません」という説明はありません) – user2407038
'ST'はダイナミックに割り当てられたメモリとそのメモリへのポインタ/参照を許可します。原則として、すべてのメモリを 'runST'の終わりに解放できるように設計されています。そのためには、ポインタが 'runST'をエスケープできないことが不可欠です。このようなエスケープされたポインタはまた、評価順序付けに関連する奇妙な効果を引き起こす。 'f(runST $ writeSTRef r True)+ g(runST $ readSTRef r)'は、どのrunSTが最初に評価されるかによって、異なる結果を評価することができます。参照透明性は、このような注文問題を回避するためのものです。 – chi