증가x을 인수로 사용하여 하스켈에서이 소스를 다시 작성할 수 있습니까?Haskell의 함수에서 전역 변수를 사용하지만 참조가 아닌
increase 0 _ = return()
increase n x = do
modifySTRef x (+n)
increase (n - 1) x
calculation n = runST $ do
x <- newSTRef 0
increase n x
readSTRef x
증가x을 인수로 사용하여 하스켈에서이 소스를 다시 작성할 수 있습니까?Haskell의 함수에서 전역 변수를 사용하지만 참조가 아닌
increase 0 _ = return()
increase n x = do
modifySTRef x (+n)
increase (n - 1) x
calculation n = runST $ do
x <- newSTRef 0
increase n x
readSTRef x
당신이 소스 파일의 최상위에 좋아 달성 할 [0] 방법은 없습니다 : 단순히 그런 전역의 "실행"의 순서에 보장이 없다가. 실제로, 전혀 실행이 없습니다 (그러므로 이전의 겁나는 따옴표). 은이어야합니다. runST
아래의 실행으로 함께 ST
액션을 작성해야합니다.
즉, 전역 변수의 이름을 처음 선언 할 때와 같이 불순한 바인딩은 runST
블록에서 수행되어야하며 따라서 모듈의 최상위 바인딩 아래 수준에 있습니다.
그러나 내보낼 때를 제외하고는 해당 최상위 바인딩에 대해서는 특별한 것이 없습니다. 당신은 단지 runST
의 내부에 새로운 "최상위"을 구축 할 수 있습니다 :
stThread :: ST s Int
stThread = do
x <- newSTRef
let increase :: Int -> ST s()
increase 0 = return()
increase n = do
modifySTRef x (+n)
increase (n - 1) x
increase 10
increase 20
readSTRef x
calculation :: Int
calculation = runST stThread
[0] 음, 파괴 하스켈 의미를 필요로하지 않는 어떤 정결 한 방법입니다. 때로 사람들은 속임수를 쓰지만, 선의의 어떤 종류로든 그것을 추천 할 수는 없습니다.
ST
참조를 가질 수 없습니다. 그렇게하면 참조 투명성이 깨질 수 있습니다. 다음을 고려하십시오 :
x :: STRef s Int
x = magicallyCreateSTRef 0
test1 :: (Int, Int)
test1 = (runST (modifySTRef x (+1) >> readSTRef x)
, runST (modifySTRef x (+1) >> readSTRef x))
test2 :: (Int, Int)
test2 = (y, y)
where y = runST (modifySTRef x (+1) >> readSTRef x)
이제 test1
의 값은 무엇입니까? 평가 순서에 따라 (0,1)
또는 (1,0)
이 될 수 있습니다. 이것은 이미 하스켈이 부서 졌다는 아주 나쁜 징후입니다. 요점을 더욱 명확하게하기 위해 test2
은 참조 투명성으로 인해 test1
과 분명히 동일해야합니다. 여전히 test2
은 내부에 다른 값을 가진 쌍을 생성 할 수 없습니다.
따라서 최상위 레벨 STRef
을 가질 수 없습니다. 최대 수준의 IO 참조를 가질 수 있습니다 (예 :
x :: IORef Int
x = unsafePerformIO (newIORef 0)
는만큼 위의 참조가 단형이며,이 즉 안전 및 참조 투명성을 입력 하스켈의 주요 기능을 중단하지 않습니다 (IORef Int
및 IORef [Int]
은 IORef [a]
이 아닌, 확인하다). 그것은 금지 된 기능 unsafePerformIO
을 사용하기 때문에 여전히 약간 해킹으로 여겨지지만, 적어도 이것은 잘 알려진 안전한 사용법입니다.
왜 IO 참조가 허용되고 ST 참조가 아닌가? ST
모나드에는 순수한 코드 (예 : test1
및 test2
)에서 모나드 값을 사용할 수있는 이스케이프 기능 runST
이 있기 때문에 대신 IO
에는 유사한 runIO
이스케이프 기능이 없습니다.
작성하고 싶은 코드 종류를 알려주십시오. – ErikR