2013-07-22 11 views
5

これはこれに関する参考質問です。StackOverflow in continuation monad
私は少し演奏し、いくつかの説明が必要です。スタックオーバフローを防ぐために、ディレイは連続モナドでどのように正確に機能しますか?

1)私はこれを仮定:

member this.Delay(mk) = fun c -> mk() c 

は、これらの間のtoyvoで示したような計算ワークフローの動作がdiffrenceを行います:

cBind (map xs) (fun xs -> cReturn (f x :: xs)) 

cBind (fun c -> map xs c) (fun xs -> cReturn (f x :: xs)) 

だから私は正確に何であるか理解していませんトリック、
(fun c -> map xs c)(map xs)

2だけ異なる表記で)推論問題を起こす。 - OPの2番目のマップの例では、vという値の推論問題のためにコンパイルされないことがわかりました。これはの代わりにをa -> b listと推定しています。なぜそれがこのように推測するのか? let v = f xの場合、それはよく推測するでしょう。

3)VSがツールチップで不正確な型シグネチャを示していることに私には思える:モナドのリターンの 戻り値の型は次のとおりです。('e->'f)->f、バインドの戻り値の型が唯一の'c->'bている間。 - これは、バインドケースで('e->'f)cに単純化しているようですか、ここに何かがありませんか?明確化のため

おかげで、
トマス

編集 - テストダンプ:MAP_FIXED

let cReturn x = fun k -> k x 
let cBind m f = 
    printfn "cBind %A" <| m id 
    fun c -> m (fun a -> f a c) 

let map_fixed f xs = 
    let rec map xs = 
    printfn "map %A" xs 
    match xs with 
     | [] -> cReturn [] 
     | x :: xs -> cBind (fun c -> map xs c) (fun xs -> cReturn (f x :: xs)) 
    map xs (fun x -> x) 

let map f xs = 
    let rec map xs = 
    printfn "map %A" xs 
    match xs with 
     | [] -> cReturn [] 
     | x :: xs -> cBind (map xs) (fun xs -> cReturn (f x :: xs)) 
    map xs (fun x -> x) 

[1..2] |> map_fixed ((+) 1) |> printfn "%A" 
[1..2] |> map ((+) 1) |> printfn "%A" 


マップ[1。 [] CBIND [] 地図[] [2 2] マップ[2] マップ[] CBIND [] 地図[] CBIND [3] マップ[2] マップ。 3]

地図:
map [1; 2] map [2] map [] cBind [] cBind [3] [2; 3]

編集2を疑問視する:

let map f xs = 
    let rec map xs = 
     cont { 
      match xs with 
      | [] -> return [] 
      | x :: xs -> 
       let v = f x // Inference ok 
       //let! v = cont { return f x } // ! Inference issue - question 2 
       let! xs = map xs 
       return v :: xs 
     } 
    map xs id 
+0

2番目の質問に関して、推論は私のためにうまくいくようです。 – kvb

+0

私は// let!のコメントを外すと、それは私に与えられます:型の不一致。期待していますが、リストを与えました – tomasK

+0

私は間違いを見ます - 私のバインドの定義にありました - ポイント1と同様のログです - 愚かな私、関心をお寄せいただきありがとうございます。 – tomasK

答えて

3

問題はfun c -> map xs cmap xsと同じではないこと、正確です。彼らはある意味で同じ "意味"を持っていますが、ランタイムのセマンティクスは異なります。後者の場合、式を評価すると、ファンクションへのコールがxs(結果として別のファンクションを戻す)になります。一方、fun c -> map xs cを評価しないと、はすぐにmapに電話します! mapへの呼び出しは、結果の関数が実際に適用されるまで遅延されます。これは、スタックのオーバーフローを防ぐ重要な違いです。

他の質問については、2番目の質問で何を求めているのかよく分かりません。あなたの3番目の質問のために、コンパイラはBindのために可能な最も一般的な型を推測しています。あなたが期待するかもしれない伝統的なタイプはこれよりも具体的ですが、実際には、厳密に必要とされるより広い範囲の文脈でBindと呼ぶことはできません。より具体的なタイプが本当に必要な場合は、注釈を追加して署名を制約することができます。

+0

私の2番目の質問に関しては、その2番目のopの関数をコンパイルしようとすると何が問題になるのでしょうか?関数のパラメータ** f ** **のタイプは予期せぬものです。 – tomasK

+0

- "マップへの即時呼び出しは発生しません" - しかし、テストダンプによると、cBindが評価される前に - 私の編集を参照してください... – tomasK

+1

@tomasK - 'm 'あなたの' cbind'のロギングで。その行を 'printfn" cbind "に変更すると、' map_fixed'が実際に 'map'を呼び出すのを遅らせることがわかります。 – kvb

関連する問題