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
そこに分岐?1つの分岐はそれほど悪くなく、対処できますが、保釈したい場所が複数あると想像してみてください。これはすぐに醜くなります。
では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
Cont
か?より強力なものを使用する必要がないと言った場合cont
、それは使用していないということですか、reset
それともshift
どちらかですか?