2013-08-23 35 views
5

là chức năng bản đồ của tôi trong: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)));; 
;; 

có đúng không? Lazy.forcing nó như thế đã làm cho nó ghi nhớ?

Trả lời

7

Có, điều đó là chính xác.

Tuy nhiên, lưu ý rằng sẽ không có chia sẻ tính toán khi áp dụng nó theo chu kỳ thông thường/chu kỳ thay vì cơ sở dữ liệu vô hạn (như ones tại đây). Việc buộc N yếu tố đầu tiên của map succ ones sẽ vẫn áp dụng succ N lần. (Thực tế, có một số công trình nghiên cứu về ngôn ngữ cho phép phát hiện hình thức chu kỳ/chu kỳ như vậy và lập bản đồ chặt chẽ khi chúng kết thúc, xem ví dụ: dự án CoCaml.)

4

Có một số ma thuật trong loại hình lười biếng. Tôi nghĩ dễ hiểu hơn khi bạn tự mình thực hiện nó, điều này rất dễ dàng dù không thuận tiện về mặt cú pháp. Các thủ đoạn là

  • chậm trễ đánh giá sử dụng đóng cửa
  • tế bào sử dụng ref để memoize tính

đây thì rõ ràng như thế nào và khi memoization xảy ra trong 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 

nhập 'a stream = Cons of' a * 'a Lazy'.t ;;

let ones = let rec ones '() = Cons (1, Lazy'.delay ones') trong ones '() ;;

let rec map f s = match s với | Nhược điểm (h, t) -> Nhược điểm (f h, Lazy'.delay (fun() -> map f (Lazy'.force t))) ;;

+2

Mục đích của lần gián đoạn thứ hai tại 'type' a t = unit -> 'a susp ref' là gì? Bạn chỉ bao giờ quay trở lại 'fun() -> r' hoặc áp dụng' 'let s = f() in'. Tại sao bạn không thể cắt trung gian? PS: để được rõ ràng, tôi hỏi tại sao http://ideone.com/Eidm34 sẽ không hoạt động. –

+0

Đồng ý. Nó không cần thiết. Chúng ta nên gõ ''a t =' a susp ref'. Các indirection là vestigial từ một nỗ lực trước đó :) – seanmcl