私はいくつかの重要な注意点と、トーマスの答えが役に立ったと評価:それは示唆しているので、計算を表現するために名前Cont
を使用し
は私見Cont
がcontinationであることを(間違って) を混乱さ。 I 「不完全」計算を表しているので、代わりにInc
という名前を使用することを提案します。この計算には、続行に渡す準備ができている値(タイプ 'T
)が含まれています。 重要ポイント: Inc
は継続と同じものではありません。
また、のパターンマッチングなしで、識別された共用体のパターンがないと、Inc
を定義することを提案します。これにより、 のBind
が大幅に簡略化されます。我々は継続が常に がunit
を生成することを前提とすべき理由
は私もわからないんだけど、それは確かにそう 、私は以下ではこの仮定しておこう、かなり物事を簡素化します。
だから、私たちは'T -> unit
の署名を持つ任意の関数としての継続を定義することができ、私たちのようにInc
を定義することができます。英語では
type Inc<'T> =
('T -> unit) -> unit
、Inc
が与えられたにそのラップ'T
値を渡します結果としてunit
となります。
次に、Bind
関数の明示的な署名が必要です。それはモナドなので、我々はそれがこのように見えるように持って知っている:
let bind (inc : Inc<'T>) (wrap : 'T -> Inc<'U>) : Inc<'U> =
のでbind
は(タイプ'T
の)不完全な計算を取り、(タイプの不完全な計算で生の値を「ラップ」できる機能)、その型の新しい不完全計算を返します。このシグネチャに基づいて、bind
はInc
を返す必要があり、Inc
は入力を継続する関数であることがわかります。だから我々はbind
の実装は次のように開始する必要があることを知っている:
fun (cont : 'U -> unit) -> ...
私たちの仕事は、与えられたInc
の内側に包まれています'T
値を抽出して、与えられたラッパー関数を使用して、それを再ラップすることです。 重要な洞察:この値を取得するには、Inc
に今すぐ書き込む続きを渡すよう依頼するしかありません。この「人工的な」続きの中で、抽出された値を再ラップし、それを呼び出し側に返します。
let bind (inc : Inc<'T>) (wrap : 'T -> Inc<'U>) : Inc<'U> =
fun (cont : 'U -> unit) -> // return an Inc, which is a function that takes a continuation as input
inc (fun t -> // force the incomplete computation to cough up its wrapped value
(wrap t) cont) // wrap the raw value so it can be sent to the given continuation
これは[こちら]偉大な長さで覆われている(http://stackoverflow.com/questions/3322540/how-and-why-does-the-haskell-cont:完成
bind
関数は、したがって、このようになります-monad-work)、特に@C。 A.マッキャンの答えは注目に値する(恐らくは2回読んだり)。 – scrwtp