4

次のdoブロックなので:

do
  x <- foo
  y <- bar
  return x + y

次の形式に脱糖されます:

foo >>= (\x -> bar >>= (\y -> return x + y))

ここに継続は\x -> ...ありませんか?y -> ...

の定義で継続をキャプチャする方法があるかどうか疑問に思いましたがbind、タイプを正しく取得できません。すなわち:

data Pause a = Pause a | Stop

instance Monad Pause where
  return x = Stop
  m >>= k = Pause k         -- this doesn't work of course

今、私はタイプをいじってみました:

data Pause a = Pause a (a -> Pause ???) | Stop
                       ------- k ------

しかし、これも機能しません。これらの暗黙の継続をキャプチャする方法はありませんか?

ところで、私はモナドについて知っていますCont、私はただ実験して物事を試しています。

4

2 に答える 2

1

よくわかりませんが、少し考えさせてください。継続をキャプチャすることの意味がよくわかりません。たとえば、 doブロック全体を構造体にキャプチャできます。

{-# LANGUAGE ExistentialQuantification #-}

import Control.Monad

data MonadExp b = Return b | forall a. Bind (MonadExp a) (a -> MonadExp b)

instance Monad MonadExp where
    return x = Return x
    f >>= g = Bind f g

例えば:

block :: MonadExp Int
block = do
    x <- return 1
    y <- return 2
    return $ x + y

instance Show (MonadExp a) where
    show (Return _) = "Return _"
    show (Bind _ _) = "Bind _ _"

print block
>> Bind _ _

そして、全体を評価します。

finish :: MonadExp a -> a
finish (Return x) = x
finish (Bind f g) = finish $ g (finish f)

print $ finish block
>> 3

または、ステップスルーしてパーツを確認します

step :: MonadExp a -> MonadExp a
step (Return _) = error "At the end"
step (Bind f g) = g $ finish f

print $ step block
>> Bind _ _
print $ step $ step block
>> Return _

さて、私がそれについてもっと考えると、それはおそらくあなたが求めているものではありません。しかし、多分それはあなたが考えるのを助けるでしょう。

于 2012-07-05T23:27:16.733 に答える
1

さて、あなたのラムダが厳密な意味での継続であるかどうかはわかりませんが、私の目にはこの概念に似ています。

ただし、それらが継続である場合、脱糖されたモナディックコードはすでに継続渡しスタイル(CPS)で記述されていることに注意してください。継続を「キャプチャ」する制御オペレータの通常の概念は、ダイレクトスタイルのプログラムに基づいています。「キャプチャされた」継続は、直接スタイルのプログラムでは暗黙的ですが、CPS変換によって明示的になります。

脱糖されたモナディックコードはすでにCPSなどに含まれているので、質問を組み立てる方法は、モナディックコードがCPSコードで可能な制御フローのトリックの一部を表現できるかどうかです。通常、これらのトリックは、CPSレジームでは、関数がその継続を呼び出すことによって終了するのが一般的である一方で、関数はその継続を選択した別の関数に置き換えることを選択できるという考えに要約されます。この置換継続は、元の継続を参照して構築できるため、必要に応じて元の継続を「復元」できます。したがって、たとえば、コルーチンは相互の「置換/復元」サイクルとして実装されます。

そして、この観点から見ると、あなたの答えはほとんどノーだと思います。CPSは、でfoo >>= bar、が呼び出されるfooかどうかを選択できる必要があり、の代わりを提供できる必要がありますが、それ自体はこれを行うためのメカニズムを提供せず、さらに重要なことに、実行を制御します流れではなく。一部の特定のモナドはその一部またはすべてを実装しますが(たとえば、モナドは結果を生成することで実行を控えることができます)、そうでないものもあります。barfoobar(>>=)foo(>>=)fooMaybefoobarNothing

私が得ることができる最も近いものは、見捨て(>>=)て代わりにこれを使用することです:

-- | Execute action @foo@ with its "continuation" @bar@.
callCC :: Monad m => ((a -> m b) -> m b) -> (a -> m b) -> m b
foo `callCC` bar = foo bar

ここで、使用fooするかどうかを選択できますbarcallCCしかし、これは本当にただのことに注意して($)ください!

于 2012-07-05T23:27:58.870 に答える