Prolog `shift`/`reset` 与其他语言有何不同?

Lyn*_*ynn 7 continuations haskell prolog swi-prolog delimited-continuations

我在这里找到了 Haskell 中移位重置分隔延续的示例:

resetT $ do
    alfa
    bravo
    x <- shiftT $ \esc -> do
       charlie
       lift $ esc 1
       delta
       lift $ esc 2
       return 0
    zulu x
Run Code Online (Sandbox Code Playgroud)

这会:

  1. 履行alfa

  2. 履行bravo

  3. 履行charlie

  4. 绑定x到1,从而执行zulu 1

  5. 从末尾掉下来resetT,然后跳回到后面esc 1

  6. 履行delta

  7. 绑定x到2,从而执行zulu 2

  8. 从末尾掉下来resetT,然后跳回到后面esc 2

  9. 逃离resetT,导致它产生 0

我不知道如何使用 SWI-Prolog 的shift/1reset/3编写等效代码。

下面的代码是我的尝试。输出是相同的,但看起来很混乱和倒退,我觉得我误用了与Haskell 示例中的和Ball类似的东西。另外,我不知道该怎么办。esc 1esc 2return 0

% not sure about this...
example :-
  reset(step, ball(X), Cont),
  ( writeln("charlie"), X=1, call(Cont), fail
  ; writeln("delta"), X=2, call(Cont)).

step :-
  writeln("alfa"),
  writeln("bravo"),
  shift(ball(X)),
  format("zulu ~w~n", X).
Run Code Online (Sandbox Code Playgroud)

我很困惑:Scheme/Haskell/ML 风格的移位重置和 Prolog 移位重置看起来几乎完全不同!例如,您将 lambda 传递到 Haskell 中shiftT,但没有将目标传递到 Prolog 的 shift/1 中。

Prolog 中 Haskell 的\esc -> ... esc 1or等​​价物在哪里return 0BallProlog 的or的 Haskell 等价物在哪里call(Cont)

我觉得上面 Haskell 示例的“正确”移植可以回答这些问题。

cha*_*sey 5

    \n
  1. 和运算符最初来自Danvyreset菲林斯基,1990。\xe2\x80\x9c 抽象控制\xe2\x80\x9dHaskell Control.Monad.Trans.Cont中对应的接口符合原始语义,除了一些类型限制之外。SWI-Prolog 中的分隔延续接口并不完全是原始的和。它们与Felleisen,1988 的提示和控制Sitaram\xe2\x80\x99 的 fcontrol 和 run 操作符关系更密切。shiftresetshift

    \n
  2. \n
  3. 通常,将定界延续程序从 Haskell 转换为 Prolog 并不困难。您的示例中的困难在于它使用esc不同的值调用相同的延续两次。例如,

    \n
    example :-\n  reset(step, ball(X), Cont),\n  X=1, call(Cont),\n  X=2, call(Cont).\n
    Run Code Online (Sandbox Code Playgroud)\n

    第一个已经绑定后call(Cont),您无法将其重新绑定。X12

    \n

    TomSchrijvers 的建议是使用copy_term/2使用新的统一变量创建延续的副本(是的,延续也是 SWI-Prolog 中的术语!),因此您的示例的 Prolog 等效项是

    \n
    example(X) :-\n  reset(step, Ball, Cont),\n  copy_term(Cont+Ball, Cont1+Ball1),\n  copy_term(Cont+Ball, Cont2+Ball2),\n  writeln("charlie"),\n  ball(X1) = Ball1,\n  X1=1, reset(Cont1, _, _),\n  writeln("delta"),\n  ball(X2) = Ball2,\n  X2=2, reset(Cont2, _, _),\n  X=0.  \n\nstep :-\n  writeln("alfa"),\n  writeln("bravo"),\n  shift(ball(X)),\n  format("zulu ~w~n", X),\n  shift(ball(X)).\n\n?- example(X).\nalfa\nbravo\ncharlie\nzulu 1\ndelta\nzulu 2\nX = 0.\n
    Run Code Online (Sandbox Code Playgroud)\n
  4. \n
\n

更详细的讨论,请参阅https://swi-prolog.discourse.group/t/naming-clarification-about-delimited-continuation-reset-3-and-shift-1

\n