2013-08-23 10 views
5

Czy moja funkcja map w:Ocaml - Lazy.force

type 'a stream = Cons of 'a * 'a stream Lazy.t 

let rec ones = Cons(1, lazy(ones));; 

let rec map (f:'a -> 'b) (s:'a stream) : 'b stream = 
    match s with 
    |Cons(h,t) -> Cons(f h, lazy (map f (Lazy.force t)));; 
;; 

prawidłowe? Czy Lazy. Wymuszenie tego już sprawi, że zostanie to zapamiętane?

Odpowiedz

7

Tak, jest prawidłowa.

Należy jednak pamiętać, że nie będzie podziału współużytkowania obliczeń podczas stosowania go na regularnej/cyklicznej zamiast nieskończonej strukturze danych (jako ones tutaj). Wymuszenie N pierwszych elementów map succ ones będzie nadal obowiązywać N razy. (W rzeczywistości istnieją prace badawcze nad językami, które pozwoliłyby wykryć taką formę regularności/cykli i zakończyć ich ścisłe mapowanie, patrz np. Projekt CoCaml.)

4

W lamzie typu ocaml jest trochę magii. Wydaje mi się, że łatwiej jest zrozumieć lenistwo, kiedy sam je implementujesz, co jest łatwe, ale nie tak wygodne pod względem składniowym. Sztuczki są

  • ocena opóźnienie przy użyciu zamknięć
  • komórki wykorzystują wg memoize obliczeń

Tutaj jest jasne, w jaki sposób i kiedy memoization dzieje podczas Lazy'.force.

module Lazy' : sig 
    type 'a t 
    val delay: (unit -> 'a) -> 'a t 
    val force: 'a t -> 'a 
end = struct 
    type 'a susp = 
    | NotYet of (unit -> 'a) 
    | Done of 'a 

    type 'a t = 'a susp ref 

    let delay f = ref (NotYet f) 

    let force f = 
    match !f with 
    | Done x -> x 
    | NotYet f' -> 
     let a = f'() in 
     f := Done a; 
     a 
end 

wpisz "strumień = Wady" a * "strumień Lazy'.t ;;

pozwolić te = pozwolić ones rec() = (1, Wady Lazy'.delay ones ') w te'() ;;

let rec map f s = mecz s z | Wady (h, t) -> Wady (f h, Lazy'.delay (fun() -> map f (Lazy'.force t))) ;;

+2

Jaki jest cel drugiego kierunku w "typie" a t = jednostka -> "a susp ref"? Zwracasz tylko 'fun() -> r' lub stosując' 'let s = f() in'. Dlaczego nie możesz przeciąć pośrednika? PS: jasne, pytam, dlaczego http://ideone.com/Eidm34 nie zadziała. –

+0

Uzgodnione. To niepotrzebne. Powinniśmy napisać '' a t = 'a susp ref'. Indywidualność jest szczątkowa od wcześniejszej próby :) – seanmcl