2013-08-23 20 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