2009-06-24 8 views
12

나는 기능이 있습니다Haskell에서 어떻게 실제로 'get'할까요?/get/initial 상태입니까?

test :: String -> State String String 
test x = 
    get >>= \test -> 
    let test' = x ++ test in 
    put test' >> 
    get >>= \test2 -> put (test2 ++ x) >> 
    return "test" 

나는 거의이 기능을 통해 어떤 일이 일어나는지 이해할 수있다, 그리고 나는 모나드의 묘리를 터득하기 시작하고있다. 어떻게 든 초기 상태 "testtest"을 얻는다 '시험'에

runState (test "testy") "testtest" 

'수'기능 : 내가 이해하지 못하는 것은 내가이 프로그램을 실행할 때 방법이다. 누군가 이것을 해체하고 설명해 줄 수 있습니까?

감사합니다.

답변

18

원래이 내용을 의견으로 게시하려고했지만 조금 더 설명하기로 결정했습니다.

엄밀히 말하면, get은 인수를 "취하지"않습니다. 나는 현재 일어나고있는 많은 것들이 당신이 보지 못하고있는 것, 즉 모나드 모나드의 인스턴스 정의에 가려져 있다고 생각합니다.

get은 실제로 MonadState 클래스의 한 메서드입니다. (모나드는 "래퍼"에 대한로 생각 될 수 있다는 것을 기억 get 그냥 아주 기본적인 상태 모나드를 반환 즉

get = State $ \s -> (s,s) 

: 국가 모나드는 get의 다음과 같은 정의를 제공 MonadState의 인스턴스 계산에), 어떤 입력 s 계산에 결과로 s의 쌍을 반환합니다. 이 초기 상태를 때까지 >>= 계산되지 않는 새로운 계산을 얻을 것입니다, 그래서

m >>= k = State $ \s -> let 
    (a, s') = runState m s 
    in runState (k a) s' 

:

우리가 볼 필요가 다음 일은 국가가 thusly 히 정의하는 >>=입니다 (이것은 "wrapped"형태의 모든 State 계산에 해당됨). 이 새로운 계산의 결과는 >>=의 오른쪽에있는 것을 왼쪽에있는 계산을 실행 한 결과에 적용하면 얻을 수 있습니다.(그것은 꽤 복잡한 문장입니다. 추가 읽기 1 또는 2가 필요할 수도 있습니다.)

나는 모든 일을 "desugar"하는 것이 매우 유용하다는 것을 알았습니다. 그렇게하는 것이 훨씬 더 많은 타이핑을 필요로하지만 귀하의 질문에 대한 답을 매우 명확하게해야합니다 (get이 어디에서 왔는지). ... 다음은 psuedocode 고려되어야합니다

test x = 
    State $ \s -> let 
     (a,s') = runState (State (\s -> (s,s))) s --substituting above defn. of 'get' 
     in runState (rightSide a) s' 
     where 
      rightSide test = 
      let test' = x ++ test in 
      State $ \s2 -> let 
      (a2, s2') = runState (State $ \_ -> ((), test')) s2 -- defn. of 'put' 
      in runState (rightSide2 a2) s2' 
      rightSide2 _ = 
      -- etc... 
우리의 함수의 최종 결과가 나머지를 만들기 위해 초기 값 ( s)가 필요합니다 새로운 주 계산이 있음이 분명해야한다

물건은 일어난다. runState 전화로 s"testtest"을 입력했습니다. 위 의사 코드에서 "testtest"를 s으로 대체하면 가장 먼저 발생하는 것은 "testtest"를 '초기 상태'로 사용하여 get입니다. 이것은 ("testtest", "testtest") 등을 산출합니다.

그래서 여기에서 get이 초기 상태 인 "testtest"를 얻습니다. 희망이 도움이!

+2

내가 인수 할 때 더 나은 단어를 생각할 수 없었다. 이 매우 상세한 설명에 감사드립니다. – Rayne

5

State 유형 생성자가 실제로 무엇인지, 그리고 runState가 그것을 어떻게 사용하는지 자세히 살펴 보는 데 도움이 될 수 있습니다. GHCi에서 : 국가의 유형 및 반환 유형 :

Prelude Control.Monad.State> :i State 
newtype State s a = State {runState :: s -> (a, s)} 
Prelude Control.Monad.State> :t runState 
runState :: State s a -> s -> (a, s) 

State는 두 개의 인수를 취합니다. 이것은 초기 상태를 취하고 반환 값과 새 상태를 반환하는 함수로 구현됩니다.

runState은 초기 입력과 (아마도) 다른 하나를 적용하여 (결과, 상태) 쌍을 검색합니다.

test 함수는 State 유형 함수의 큰 구성이며 각 함수는 상태 입력을 가져 와서 (결과, 상태) 출력을 내고 프로그램에 맞는 방식으로 서로 꽂습니다. runState 모두 상태 시작점을 제공합니다.

이 문맥에서 get은 상태를 입력으로 사용하고 결과가 입력 상태가되도록 (결과, 상태) 출력을 반환하는 함수이며 상태는 변경되지 않습니다 (출력 상태는 입력입니다. 상태). 즉, get s = (s, s)

+1

클릭하면 클릭! 빙고. 고마워요, 당신은 설명을 클릭하도록 만들었습니다. 나는 실제로 그것이 인수를 '인수했다'는 것을 결코 깨닫지 못했다. Hehe. 감사. – Rayne

1

그레이엄 허튼 (Graham Hutton)의 Programming in Haskell의 8 장 ("기능적 구문 분석기")을 제대로 이해할 때까지 여러 번 반복하고, 자습서 All About Monads으로 이동하여이 클릭을 만들어주었습니다.

모나드의 문제점은 일반적인 프로그래밍 배경에서 오는 사람들이 매우 다른 점을 발견하여 여러 가지 점에서 유용합니다. 제어 흐름과 핸들링 상태가 동일한 메커니즘으로 처리 될 수있을만큼 충분히 유사 할뿐만 아니라 충분히 뒤로 물러나는 경우도 마찬가지입니다.

C (forwhile 등)의 제어 구조를 고려했을 때 주현이 나타났습니다. 가장 일반적인 제어 구조는 다른 명령문보다 먼저 하나의 명령문을 넣는 것입니다. 하스켈을 공부하기까지는 1 년이 걸렸다.

+0

답변 해 주셔서 감사합니다. 다행히도 대부분의 프로그래밍 경험은 실제로 Functional programming에 있습니다. :디 – Rayne