Program Tip

ST 모나드는 어떻게 작동합니까?

programtip 2020. 11. 8. 10:56
반응형

ST 모나드는 어떻게 작동합니까?


나는 ST 모나드가 IO의 남동생과 비슷하다는 것을 알고 있으며, 이는 다시 RealWorld마법 이 추가 된 상태 모나드입니다 . 나는 상태를 그릴 수 나는 RealWorld 어떻게 든 IO에 투입되는 사진 수 있지만, 때마다 나는의 유형 서명 쓰기 목표 명세서가 모나드 혼란 날을.STs

예를 들어 ST s (STArray s a b). s거기에서 어떻게 작동합니까? 상태 모나드의 상태처럼 참조 할 수없는 상태 (으로 인해 forall) 없이 계산간에 인위적인 데이터 종속성을 구축하는 데 사용 됩니까?

나는 단지 아이디어를 던지고 있고 그것을 설명해 줄 수있는 나보다 더 많은 지식을 가진 사람에게 정말로 감사 할 것입니다.


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서명이 있음을 기억하십시오 .

runST :: (forall s . ST s a) -> a

즉, s실행중인 계산에 대한 제약이 없어야합니다. 따라서 평가하려고 할 때 a:

a = runST (newSTRef (15 :: Int) :: forall s. ST s (STRef s Int))

결과는 유형을 갖게 STRef s Int되는데 이는이 in s외부에서 "이스케이프" 되었기 때문에 잘못된 것 forall입니다 runST. 유형 변수는 항상 내부에 나타나야 forall하며 Haskell은 forall모든 곳에서 암시 적 수량 자를 허용 합니다. 의 반환 유형을 의미있게 파악할 수있는 규칙은 없습니다 a.

다음과 같은 또 다른 예 forall: 를 이스케이프 할 수없는 이유를 명확하게 보여주기 위해 forall다음은 더 간단한 예입니다.

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 --

물론 부울이 참인지 거짓인지 따라 목록 또는 f id목록을 반환하므로 오류입니다. .NET의 예제처럼 단순히 잘못되었습니다 .CharIntST

반면에s 타입 매개 변수가 없다면 코드가 꽤 가짜 임에도 불구하고 모든 것이 제대로 타입 검사를 할 것입니다.

ST가 실제로 작동하는 방식 : 구현 측면에서 ST모나드는 실제로 모나드와 동일 IO하지만 인터페이스가 약간 다릅니다. ST모나드 를 사용할 때 실제로 얻 unsafePerformIO거나 그에 상응하는 것, 뒤에서. 이 작업을 안전하게 수행 할 수있는 이유는 모든 ST관련 함수, 특히 forall.


이것은 s타입 시스템이 안전하지 않은 일을하는 것을 막는 해킹 일뿐입니다. 런타임에 아무것도 "하지"않습니다. 유형 검사기가 모호한 작업을 수행하는 프로그램을 거부하게 만듭니다. (소위 팬텀 타입으로 타입 체커의 헤드에만 존재하며 런타임에 영향을주지 않습니다.)

참고 URL : https://stackoverflow.com/questions/12468622/how-does-the-st-monad-work

반응형