Consideriamo la seguente implementazione della monade Continuazione, per i calcoli in stile CPS rendimento e numero intero:Come convertire in stile CPS GCD calcolo di utilizzare la continuazione Monade
module Cont : sig
type 'a t = ('a -> int) -> int
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
val callCC: (('a -> 'b t) -> 'a t) -> 'a t
end = struct
type 'a t = ('a -> int) -> int
let return x =
fun cont -> cont x
let bind m f =
fun cont -> m (fun x -> (f x) cont)
let callCC k =
fun cont -> k (fun x -> (fun _ -> cont x)) cont
end
Come possiamo riscrivere il CPS- implementazione di stile del calcolo gcd (vedi How to memoize recursive functions?) e in particolare la memoizzazione per sfruttare il monito Cont?
Dopo aver definito
let gcd_cont k (a,b) =
let (q, r) = (a/b, a mod b) in
if r = 0 then Cont.return b else k (b,r)
ho cercato di utilizzare il tipo di risolutore di darmi spunto circa il tipo che la funzione Memoizzazione dovrebbe avere:
# let gcd memo ((a,b):int * int) =
Cont.callCC (memo gcd_cont (a,b)) (fun x -> x)
;;
val gcd :
(((int * int -> int Cont.t) -> int * int -> int Cont.t) ->
int * int -> (int -> 'a Cont.t) -> int Cont.t) ->
int * int -> int = <fun>
Tuttavia non potrebbe trasformare questo suggerimento in un implementazione effettiva. Qualcuno è in grado di farlo? La logica alla base dell'utilizzo di "callCC" nella funzione di memoizzazione è che se si trova un valore nella cache, allora questa è una condizione di uscita anticipata.
Il mio male per nominare CPS ciò che non lo è. Esiste un nome canonico per la forma specifica della versione "strumentabile" delle funzioni? –