왜 ST
은 다음 코드를 허용하지 않도록 설계 되었습니까? as shown in the wikibook? 이 기사에서는 ST
효과가 또 다른 ST
으로 누설 될 것이라고 제안하는 것으로 보이지만 실제로는 이유를 이해하지 못합니다.ST 참조는 투명합니까?
특정 ST s (STRef s a)
을 실행할 수없는 것 같습니다. ST
효과가 포함되어 있고 명확하게 투명하지만 그러한 사용은 여전히 유효하지 않은 것으로 간주됩니까?
직감 한 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 유형의 모든 값. ST A는'IO A '타입의 모든 값이 명확하게 투명하기 때문에 (즉, 값 자체가 아닌 결과 값을 생성하는 방법을 나타내는 계산이므로) 투명하게 나타납니다. 'ST s (STRef s A)'는'run '될 수 없지만 여전히 유효한 계산입니다; 예 : 'STREF s A -> ST s B' 형 함수를 적용하여 forall을 얻을 수 있습니다. ST s B'를 실행할 수 있습니다. 그러나 실제로 질문이 무엇인지는 확실하지 않습니다. 문제의 코드가 왜 허용되어야한다고 생각합니까? (참고 : "나는 왜 그럴지 잘 모르겠다") – user2407038
'ST'는 동적으로 할당 된 메모리와 그 메모리에 대한 포인터/참조를 허용한다. 그것은 원칙적으로 모든 메모리가'runST'의 끝에서 해제 될 수 있도록 설계되었습니다. 이를 위해서는'runST'를 벗어날 수있는 포인터가 없어야합니다. 그러한 이스케이프 된 포인터는 또한 평가 순서와 관련된 이상한 효과를 유발할 수 있습니다. f (runST $ writeSTRef r True) + g (runST $ readSTRef r)'는 어떤 runST가 먼저 평가되는지에 따라 다른 결과를 얻을 수있다. 참조 투명성은 그러한 주문 문제를 피하기위한 것입니다. – chi