【问题标题】:does call with current continuation ignore its own continuation?当前延续的调用会忽略它自己的延续吗?
【发布时间】:2016-11-27 20:48:45
【问题描述】:

我试图理解延续传递和 Call-with-current-continuation。 根据此页面: https://en.wikipedia.org/wiki/Monad_(functional_programming)#Continuation_monad CC方法的调用实现如下:

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 只能调用一个只有一层而不是更多的函数? (因为在正常控制流中调用的下一个函数将被忽略,并带有延续 x

在那种情况下,它似乎非常有限,它的实际用途是什么?

【问题讨论】:

    标签: haskell functional-programming continuations


    【解决方案1】:

    Here 你可以找到更易读的callCC 定义,并附有非常具体的解释:

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

    MonadCont 类提供了 callCC 函数,它提供了一个 与 Continuation monad 一起使用的转义延续机制。逃脱 延续允许您中止当前的计算并返回一个 立即值。它们实现了与 throwError 和 错误单子中的 catchError。

    Here你可以看到一些漂亮的例子如何使用它。

    但总的来说:callCC 不会忽略输入,但它会通过执行方式来增强您的程序。

    您正在定义一些函数,例如

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

    然后通过callCC doSomething转换为正常延续

    而正是这个panicExit input-ignoring throw-like 引起了你的注意。你的程序没有义务失败到默认值,但你可以在你喜欢的时候做。

    【讨论】:

    • 谢谢!在那个例子中:en.wikibooks.org/wiki/Haskell/… 是否意味着调用 k 将返回到前一个连续(当前)并且“返回(显示 $ y - 4)”将显示 y-4 并结束程序?
    • @lezebulon 在callCed do 块中调用k 将完全忽略此调用之后的所有操作。所以 return (show $ y - 4) 只有在 y > 20 条件是 False 时才会执行
    • 是的,但是调用时会返回什么?和k一样吗?
    【解决方案2】:

    (为了说明,让我使用更简洁的语法而不是真正的Haskell。)

    callcc f 将给定函数f 应用于当前延续k如果这个延续 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

    通过结合上面的两个示例,您可以做更复杂的事情,例如1 + callcc (\k -> 2 + (if some_complex_condition then (k 3) else 4)),如果some_complex_conditiontrue,则为1 + 3,否则为1 + (2 + 4)

    总结并回答您的问题:

    但是,我们可以看到 x 参数在这里从未使用过。

    x 被丢弃如果继续 k 被调用;然而,当k被调用时,x 被应用于“正常”返回值,如上面的示例所示。 (后一种情况对应于 continuation monad 中的return 操作。)

    附言

    为了简洁起见,我采用了一种直接的非单子语法。使用 Haskell 中的 continuation monad,如下示例

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

    调用外部延续k丢弃内部2 + []并返回3,而

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

    2 + 4

    【讨论】:

    • 不会是(如果 some_complex_condition then (k 3) else return 4) ?
    • 那是我使用“更简洁的语法而不是真正的 Haskell”的地方。 1 + callcc (\k -&gt; 2 + (if some_complex_condition then (k 3) else 4)) 的“真正的 Haskell”代码是 do a &lt;- callCC $ \k -&gt; (do b &lt;- if some_complex_condition then k 3 else return 4; return $ 2 + b); return $ 1 + a。 Haskell 中的延续单子对可能调用延续的表达式需要不同的语法(和类型)...
    • 我在 Haskell 中使用 continuation monad 添加了后记。
    猜你喜欢
    • 2015-02-11
    • 2019-09-10
    • 1970-01-01
    • 2016-08-27
    • 2012-10-14
    • 2016-12-11
    • 2010-10-20
    • 1970-01-01
    • 2011-10-30
    相关资源
    最近更新 更多