2013-03-04 2 views
3

haskell State 모나드를 배우려고합니다. 그래서 State Monad를 사용하여 난수 목록을 생성하는 함수를 작성했습니다.whats이 2 개의 매우 유사한 haskell 상태 계산의 차이점

여기가 첫 번째 버전입니다.

rnds :: Int -> [Int] 
rnds n = evalState (help (mkStdGen 007)) [] 
    where help prng = do s <- get 
      let (a, nprng) = randomR (1,6) prng         
      put (a:s) 
      if length s == n then (return s) 
          else (help nprng) 

다음은 두 번째 버전입니다.

rnds1 :: Int -> [Int] 
rnds1 n = evalState (help (mkStdGen 007)) [] 
    where help prng = do s <- get 
      let (a, nprng) = randomR (1,6) prng         
      put (a:s) 
      ns <- get 
      if length ns == n then (return ns) 
           else (help nprng) 

동일한 매개 변수의 경우 둘 다 동일한 출력을 제공합니다. 그러나 첫 번째 버전에서는리스트의 길이를 확인하기 위해 목록 (s)을 참조하고 있습니다. 그러나 내가 put (a:s)을하기 전에 s을 획득했습니다. 그래서 내가 길이를 검사 할 때 나는 put (a:s)을하기 전에 's'의 길이를 줄 것이라고 생각했습니다. 그러나 두 버전 모두 동일한 매개 변수가 제공되는 경우 첫 번째 버전의 출력이 두 번째 버전의 출력과 동일하기 때문에 그렇게 보이지 않습니다.

두 번째 버전은 적어도 나를 쉽게 이해할 수 있습니다. ns 목록의 길이를 확인하기 전에 먼저 새로운 업데이트 상태를 얻으려면 ns <- get을 수행합니다.

누군가가 나에게 무슨 일이 일어 났는지 말해 줄 수 있습니까? 하스켈이 일하는 방식이나 국가 모나드 자체에 대해 뭔가 오해 한 것 같은 느낌을받습니다.

감사합니다.

+0

do-notaion, 상태에 대한 >> =의 정의 및 가져 오기 및 붙여 넣기의 정의를 확장하십시오. http://hackage.haskell.org/packages/archive/mtl/1.1.0.2/doc /html/src/Control-Monad-State-Lazy.html#State –

답변

5

put (a:s) 
if length s == n then (return s) 

당신이 get에서 얻은 목록을 반환 rnds에서

, 아닌 상태로 한 당신에게 put, 당신은 (rnds1보다 한 의사 난수 이상을 생산하고 그렇게하는 당신은 무시한다.) 그러나 같은 목록을 돌려 준다.

4

다니엘이 지적했듯이, 나는 이것이 당신이 사용한 알고리즘으로 인한 우연의 일치라고 생각합니다. 당신은 간단한 프로그램을 사용하는 경우는 쉽게 당신이 숨겨진 상태에서 압축을 해제 한 후 값이 "마술"돌연변이이지 않았는지 확인합니다 :보기,

module Main where 
import Control.Monad.State 

test = evalState comp 1 
    where 
    comp = do 
    x <- get 
    put 2 
    y <- get 
    return (x,y) 

main = do 
    print test 

이 프로그램은 (1,2)를 출력합니다 당신 한 번 x에 "넣기"를 수행 한 후에도 "오래된"값이 분명히 있습니다.

관련 문제