Questa è una domanda di riferimento a questo: StackOverflow in continuation monad
con cui ho giocato un po 'e avrei bisogno di alcuni chiarimenti.Come funziona esattamente il delay nella monad di continuazione per impedire lo stackoverflow?
1) Suppongo che questo:
member this.Delay(mk) = fun c -> mk() c
rende il comportamento del flusso di lavoro computazionale fare il diffrence come mostrato dalla toyvo tra questi:
cBind (map xs) (fun xs -> cReturn (f x :: xs))
cBind (fun c -> map xs c) (fun xs -> cReturn (f x :: xs))
quindi non esattamente capire quale sia la trucco, quando
(fun c -> map xs c)
è solo notazione differente di (map xs)
2) Inferere problema. - Nell'esempio della seconda mappa di OP ho scoperto che non viene compilato a causa del problema di inferenza con il valore v
, perché inferisce f
come a -> b list
, anziché il desiderato a -> b
. Perché lo sottende in questo modo? Nel caso let v = f x
si dedurrebbe bene.
3) Mi sembra che VS mostra di tipo firme imprecisi inseriti nelle descrizioni comandi: tipo di ritorno del ritorno del monade è: ('e->'f)->f
, mentre il tipo di ritorno del Bind è soltanto 'c->'b
. -Sembra semplificare lo nel caso Bind, o mi manca qualcosa qui?
Grazie per il chiarimento,
Tomas
Edit - test discarica:
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"
MAP_FIXED:
mappa [1; 2] mappa [2] mappa [] cBind [] map [] cBind [3] mappa [2] mappa [] cBind [] map [] [2; 3]
mappa:
mappa [1; 2] mappa [2] mappa [] cBind [] cBind [3] [2; 3]
Modifica alla domanda 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
Per quanto riguarda la seconda domanda, l'inferenza sembra funzionare bene per me. – kvb
Se annullo il commento // let! .. mi dà: Digitare disallineamento. Aspettando un 'a ma dato un' elenco – tomasK
Finalmente vedo l'errore - era nella mia definizione di Bind - registro simile come nel punto 1 - sciocco me, grazie per interesse. – tomasK