2016-10-01 3 views
2

저는 하스켈에서 초보자입니다. 나는 상태 모나드를 사용하고자하는 상황을 경험했습니다. 적어도 모나드 모나드에 대한 튜토리얼은 100 만 개가 있지만 모두 내 주요 목표는 개념적 차원에서 이해하는 것입니다. 결과적으로 그들은 소프트웨어를 실제로 개발하는 방법을 말하는 부분 바로 앞에 멈추게됩니다. 그래서 간단한 예제를 통해 도움을 찾고 있습니다.상태 모나드를 사용하여이 간단한 코드를 작성하려면 어떻게해야합니까?

다음은 현재 사용중인 코드의 간단한 버전입니다. 보시다시피, 저는 함수를 통해 상태를 스레딩하고 있습니다. 제 질문은 do 표기법을 사용하여 코드를 다시 작성하는 방법이므로, 그렇게하지 않아도됩니다.

data Machine = Register Int 

addToState :: Machine -> Int -> Machine 
addToState (Register s) a = Register $ s+a 

subtractFromState :: Machine -> Int -> Machine 
subtractFromState (Register s) a = Register (s-a) 

getValue :: Machine -> Int 
getValue (Register s) = s 

initialState = Register 0 

runProgram = getValue (subtractFromState (addToState initialState 6) 4) 

코드는 레지스터에 추가 그것에서 빼기, 그 값을 얻을 수있는 간단한 추상 하나의 레지스터를 가지고 기계와 지침을 시뮬레이션합니다. 끝에있는 "프로그램"은 레지스터를 0으로 초기화하고, 6을 더하고, 4를 빼고, 결과는 물론 2를 반환합니다.

나는 상태 모나드의 목적을 이해합니다.), 그리고 나는 내가 내가 아직도 확실히 변환하는 방법을 모른다 읽은 모든 자습서에도 불구하고, 그러나

runProgram :: ??????? 
runProgram = do 
    put 0 
    addToState 6 
    subtractFromState 4 
    value <- getValue 
    return value 

같은 끝낼 수 있도록 저를이를 다시 쓸 수있을 것으로 기대 내 코드를이 양식에 추가하십시오.

물론 내 실제 컴퓨터의 상태는 훨씬 복잡하며 출력 (다른 컴퓨터로 전달됨) 및 다양한 다른 것들도 지나치므로 간단하게 만드는 것이 좋습니다. 이 단순화 된 예제를 위해이를 수행하는 방법을 아는 것은 매우 큰 도움이 될 것입니다.

업데이트 : 이명박의 위대한 대답 한 후는 지금이 작업을 수행하는 방법을 알고,하지만 난 여러 상호 작용하는 기계가있을 때 같은 우아한 형태로 코드를 작성하는 방법에 갇혔어요. 나는 그것에 대해 a new question에 물었다.

import Control.Monad.State.Lazy 

data Machine = Register Int 

addToState :: Int -> State Machine() 
addToState i = do 
     (Register x) <- get 
     put $ Register (x + i) 

subtractFromState :: Int -> State Machine() 
subtractFromState i = do 
     (Register x) <- get 
     put $ Register (x - i) 

getValue :: State Machine Int 
getValue = do 
     (Register i) <- get 
     pure i 

는 다음이 상태 계산으로 그들을 결합 할 수 있습니다 :

program :: State Machine Int 
program = do 
    addToState 6 
    subtractFromState 4 
    getValue 

마침내 당신이 evalState이 계산을 실행할 수 있습니다 필요

답변

7

먼저 당신이 State Machine a 값을 반환하는 기존 기능을 변환해야 최종 결과를 얻고 상태를 삭제하려면

runProgram :: Int 
runProgram = evalState program (Register 0) 
+0

고맙습니다. 이것은 매우 귀중한 것입니다. 나는 그것을 실행하기 위해 많은 변화를 만들어야 만했다. (나는 그것에 대해 전혀 불평하지 않는다. 그렇게하는 것이 매우 유익했다.) 나는 당신의 대답으로 그들을 편집 할 것인지 아니면 그대로 두어야 할 지 잘 모르겠습니다. 당신이 선호하는 것이 있다면 알려주십시오. – Nathaniel

+0

@ Nathaniel - 원하는대로 수정할 수 있습니다. – Lee

+0

더 도움이되는 경우이 스타일로 프로그래밍하는 방법에 대한 자세한 내용은 [질문에 따르기] (http://stackoverflow.com/questions/39813675/simulating-interacting-stateful-objects-in-haskell)를 참조하십시오. 여러 개의 상호 작용하는 상태 저장 객체가 있습니다. – Nathaniel

관련 문제