2016-07-24 6 views
1

私は継続通行と通話継続通話を理解しようとしています。このページ1として 次のようにCC法を用い https://en.wikipedia.org/wiki/Monad_(functional_programming)#Continuation_monadコールが実装されている:現在の継続で呼び出しても、それ自体の継続を無視しますか?

call_cc :: ((a -> (b -> r) -> r) -> (a -> r) -> r) -> (a -> r) -> r 
call_cc f k = f (\t x -> k t) k 

このsignatureimplementationにより説明したように。

しかし、xパラメータはここでは使用されないことがわかります。 fに渡された継続が常に無視されることを意味しますか?最初の継続kは常にそれを置き換えていますか? その場合、call-with-ccは1レベルの深さではなくそれ以上の関数を呼び出すことができるという意味ですか? (通常の制御フローで呼び出される次の関数は、継続すると、xは無視されます)

その場合は非常に制限されているように見えますが、実際にはどのような使用ですか?

答えて

2

Hereあなたは非常に具体的な説明をcallCCのより読みやすい定義を見つけることができます:

class (Monad m) => MonadCont m where 
    callCC :: ((a -> m b) -> m a) -> m a 

MonadContクラスは継続モナドで使用するために エスケープ継続メカニズムを提供callCC機能を提供します。エスケープ 継続を使用すると、現在の計算を中止してすぐに 値を返すことができます。エラーモナド内でthrowErrorと catchErrorと同様の効果が得られます。

Hereあなたはそれを使用する方法のいくつかの非常に良い例を見ることができます。

しかし、一般的には:callCCは入力を無視しませんが、それを行う方法で手続きを強化します。

あなたは

doSomething panicExit = do 
    ... 
    when failCondition $ panicExit inputToStartOver 
    ... 

のようないくつかの関数を定義してから目を引いたcallCC doSomething

そして、まさにこのpanicExit入力無視スロー等を介して、通常の継続に変換しています。手続きはデフォルト値に失敗する義務はありませんが、好きなときに実行することができます。

+0

ありがとうございます! その例:https://en.wikibooks.org/wiki/Haskell/Continuation_passing_style#Deciding_when_to_use_k これは、以前の連絡先(現在の連絡先)に戻り、返信($ y - 4を表示) "はy-4を表示してプログラムを終了しますか? – lezebulon

+0

@lezebulon 'callC'ed' do'ブロックで 'k'を呼び出すと、この呼び出し後のすべてのアクションは完全に無視されます。だから 'return(show $ y - 4)'は 'y> 20'の条件が' False'の場合にのみ実行されます – Odomontois

+0

yesしかし、呼び出されたときに何を返すのですか?それはkと同じですか? – lezebulon

1

(博覧会のために、私はより簡潔な構文ではなく、本当のハスケルを使用してみましょう。)

callcc f現在の継続kに与えられた機能fを適用します。 この続行kが別の継続xで呼び出された場合、後続の継続xは実際にはで破棄されます。例えば

は、1 + callcc (\k -> 2 + (k 3))で、変数k[]が戻り値が満たされなければならないそこに孔外継続1 + []に結合されます。このk(k 3)のように適用された場合、の内部継続1 + (2 + [])は廃棄されます。。その結果、式全体は1 + 3になり、4と評価されます。一方

1 + callcc (\k -> 2 + 4)で、継続kが呼び出されず、式全体が1 + (2 + 4)を生み出すん、それは、7です。

上記の2つの例を組み合わせることで、あなたはtrue、または1 + (2 + 4)そうです1 + 3some_complex_condition場合与える、1 + callcc (\k -> 2 + (if some_complex_condition then (k 3) else 4))のようなより複雑なことを行うことができます。

は総括し、あなたの質問に答えるために:

しかし、我々はXパラメータは、ここで使用されることはありませんことを確認することができます。継続kが呼び出された場合

xが廃棄されます。ただし、kで、が呼び出されていない場合は、上記の例のようにxが「通常の」戻り値に適用されます。 (後者の場合は、継続モナドにおけるreturnの操作に相当する)

P.S.

上記の説明では、簡潔にするために、モナドではない直接の構文を採用しました。

callCC (\k -> do r <- (k 3); return (2 + r)) 

、次の例をハスケルで継続モナドを使用すると、インナー2 + []を廃棄外側継続kを呼び出し、

callCC (\k -> do r <- (return 4); return (2 + r)) 

2 + 4を与えながら、3を返します。

+0

はそうではありません(some_complex_condition then(k 3)else * return * 4)? – lezebulon

+0

これは、私が「本物のHaskellよりも簡潔な構文」を使用したところです。 1 + callcc(\ k - > 2 +(some_complex_condition、(k 3)else 4))の場合の ''本当のHaskellコードは '' do a < - callCC $ \ k - >(do b < - if some_complex_condition、次にk 3、それ以外の場合は4; return $ 2 + b); $ 1 + aを返します。 Haskellの継続モナドには、継続を呼び出す可能性のある式の構文(および型付け)が必要です。 – FPstudent

+0

Haskellの継続モナドを使用してポストスクリプトを追加しました。 – FPstudent

関連する問題