[英]Is ST referentialy transparent?
為什么ST
設計為不允許以下代碼,如wikibook所示 ? 這篇文章似乎暗示如果允許的話, ST
效應會泄漏到另一個ST
,但我真的不明白為什么。
似乎我無法運行特定的ST s (STRef sa)
。 ST
效果是否包含且引用是否透明,但這種使用仍然被視為無效?
Intuition告訴我, 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是參考透明的。
很長一段時間,這只是猜測和相信,只有今年我們有一個適當的證據:
Monadic封裝狀態的邏輯關系:在runST存在的情況下證明上下文等價
Amin Timany,LéoStefanesco,Morten Krogh-Jespersen,Lars Birkedal
POPL 2018有條件地接受
http://iris-project.org/ 預印PDF
我真的不明白你在問什么,所以我假裝你的問題是:
為什么ST設計為禁止
runST (newSTRef True)
?
如果允許,它將不再是引用透明的:
main = do
let r = runST (newSTRef True)
evaluate (runST (writeSTRef r False))
print (runST (readSTRef r))
此代碼將輸出False
。
main = do
evaluate (runST (writeSTRef (runST (newSTRef True)) False))
print (runST (readSTRef (runST (newSTRef True))))
此代碼(在每個用戶中內聯r
的結果)將輸出True
,因為runST (newSTRef True)
每個實例runST (newSTRef True)
將分配新的STRef
變量。
實際實現runST
的方式可確保在ST s
操作中分配的所有資源都無法轉義該操作。
IO
和ST s
之間的區別在於沒有runIO
功能。 您可以創建多個獨立的IO
操作,但沒有runIO
它們runIO
(它們只是值)。 實際運行IO
操作的唯一方法是將其綁定到main
並讓運行時系統選擇它(就像在main
包含一個隱式runIO
),因此只有一個IO
動作將在程序。
當然,這個單一動作可以通過組合多個較小的動作來組成,但最終它仍然是一個整體。 另一方面, runST
允許獨立執行多個ST s
動作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.