계속해서 할 수없는 callCC로 무엇을 할 수 있습니까?


9

callCC를 이해하는 데 정말로 어려움을 겪고 있습니다. 나는 Continuations의 힘을 얻었고 멋진 컨셉을 만들기 위해 일부 프로젝트에서 컨셉을 사용하고 있습니다. 그러나보다 큰 기능을 가진 것을 사용할 필요는 없었습니다 cont :: ((a->r)->r)-> Cont r a.

그것을 사용한 후에는 왜 그들이 모든 모나드의 어머니 인 Cont Monad라고 부르는지 이해가 되겠지만, 그래도 언제 사용해야하는지 모르겠는데, 이것이 callCC바로 제 질문입니다.


어떻게 사용 Cont했습니까? 보다 강력한 무언가를 사용할 필요가 없다고 말하면 사용 cont하지 않았 reset거나 shift둘 중 하나 를 의미하지 않습니까?
KA Buhr

내가 사용하지 않은 resetshift. 주어진 작업이 다른 프로세스에 의해 해결 될 때까지 일시 중단 될 수있는 eembedded 언어를 정의한 다음 주어진 "연속"으로 다시 시작했습니다. 아마도 Cont Monad에 대한 많은 경험이 있다는 인상을 줄 수 있지만 실제로는 그렇지 않습니다. callCC를 이해하고 싶습니다
Alejandro Navas

답변:


10

callCC "초기 반환"의미론을 제공하지만, 단정 한 맥락에서.

doOne하고 싶다고 말하고을 반환 True하면 즉시 중지하고 그렇지 않으면 doTwo및 로 이동합니다 doThree.

doOne :: Cont r Bool
doTwo :: Cont r ()
doThree :: Cont r ()

doThings :: Cont r ()
doThings = do
    one <- doOne
    if one
        then pure ()
        else do
            doTwo
            doThree

if지점을 보시겠습니까? 하나의 지점은 그렇게 나쁘지 않고 다루어 질 수 있지만, 보석금을 내고 싶은 지점이 여러 개 있다고 상상해보십시오. 이것은 매우 못 생겼습니다.

함께 callCC하면 "조기 반환을"할 수 있습니다 : 당신이 분기 시점에서 구제와 중첩 계산의 나머지가 없습니다 :

doThings = callCC \ret -> do
    one <- doOne
    when one $ ret ()
    doTwo
    doThree

훨씬 더 즐겁게 읽을 수 있습니다!

더 중요한 것은 ret여기 return에 C와 같은 언어 와 같은 특별한 구문이 아니라 다른 것과 같은 값이기 때문에 다른 함수에도 전달할 수 있다는 것입니다. 그런 다음 이러한 함수는 "비 로컬 리턴"이라는 것을 수행 할 수 있습니다. 즉 doThings, 여러 개의 중첩 된 호출 에서조차 계산을 "중지"할 수 있습니다 . 예를 들어, doOne의 결과를 다음 checkOne과 같은 별도의 함수로 검사하지 않을 수 있습니다 .

checkOne ret = do
    one <- doOne
    when one $ ret ()

doThings = callCC \ret -> do
    checkOne ret
    doTwo
    doThree

알겠습니다! 그리고 b당신이 callCC 내부에 더 연속 요청을 체인 할 수 있도록 기본적으로 그냥 와일드 카드입니다. 어쨌든, 일단 ret적용되면, 호출 cc에 의해 생성 된 연속은 입력 된 모든 것을 "반환"할 것이다 ret. 그것은 꽤 복잡하지만 똑똑하지만 매우 강력합니다. 그런 힘을 사용하는 것이 핵무기로 비행을 죽이는 것과는 다른 곳을 많이 보지 못합니다
Alejandro Navas

1
@caeus 다행입니다. 내 대답이 마음에 드 셨다면 수락 하시겠습니까?
Fyodor Soikin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.