2013-08-23 19 views
5

在我的地圖功能: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)));; 
;; 

正確?懶惰。強行這樣做已經使它記憶了?

回答

7

是的,這是正確的。

但是請注意,在常規/循環而不是無限數據結構上應用計算時不會共享計算(這裏爲ones)。強制N的第一個元素map succ ones仍然會應用succ N次。 (實際上有一些關於語言的研究工作可以檢測這種形式的規律性/週期,並對它們進行嚴格的映射終止,例如參見CoCaml項目。)

4

ocaml Lazy類型有一些魔力。我認爲當你自己實現時,理解懶惰更容易,雖然不是語法上的方便,但這很容易。該技巧是使用閉

  • 使用REF細胞memoize的計算
    • 延遲評估這清楚如何以及何時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 
      

      type'a stream ='a *'的一個流的缺點Lazy'.t ;;

      讓那些= 讓REC那些()=缺點(1,Lazy'.delay那些 ')中那些 '() ;;

      讓rec map f s =與s匹配 | Cons(h,t) - > Cons(f h,Lazy'.delay(fun() - > map f(Lazy'.force t))) ;;

    +2

    'type'a t = unit - >'susp ref'的第二個間接的目的是什麼?你只會返回'fun() - > r'或應用''let s = f()in'。你爲什麼不能削減中間人? PS:要清楚,我在問爲什麼http://ideone.com/Eidm34不起作用。 –

    +0

    同意。這是沒有必要的。我們應該輸入''t ='susp ref'。間接性從以前的嘗試中退化:) – seanmcl