contではできないcallCCで何ができますか?


9

私は本当に本当にcallCCを理解するのに苦労しています。私は継続の力を得て、いくつかのプロジェクトでこのコンセプトを使用して、クールなコンセプトを作成しています。しかし、私よりも優れた機能を使用する必要はありませんでしたcont :: ((a->r)->r)-> Cont r a

それを使用した後、彼らがCont Monadをすべてのモナドの母と呼んでいる理由はよくわかりますが、私はいつ使用する必要があるのか​​わかりませんcallCC


どのように使用しましたContか?より強力なものを使用する必要がないと言った場合cont、それは使用していないということですか、resetそれともshiftどちらかですか?
KA

resetまたはを使用していませんshift。私はそれを使用して、特定のアクションが別のプロセスによって解決されるまで中断でき、その後、特定の「継続」で再開できる組み込み言語を定義しました。たぶん私はCont Monadで多くの経験をしたような印象を与えますが、それほど多くはありませんが、本当にcallCCを理解したいと思います
Alejandro Navas

回答:


10

callCC 「アーリーリターン」のセマンティクスを提供しますが、モナディックコンテキストです。

あなたがしたいとdoOne、それを返した場合True、あなたはすぐに停止、そうでない場合は、あなたがに行くdoTwodoThree

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そこに分岐?1つの分岐はそれほど悪くなく、対処できますが、保釈したい場所が複数あると想像してみてください。これはすぐに醜くなります。

ではcallCC、あなたは「早期復帰」を持つことができます:あなたは、分岐点での救済と巣に計算の残りの部分を持っていません。

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

読む方がずっと楽しい!

さらに重要なことは、retここは(returnCのような言語のような)特別な構文ではなく、他のような単なる値なので、他の関数に渡すこともできます!そして、これらの関数は、いわゆる「非ローカルリターン」を実行できます。つまり、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.