ocamllazy-sequencesocaml-batteries

Lazy list of x, f x, f (f x),


Batteries.LazyList allows one to define lazy lists. I would like to define a lazy list consisting of x, f x, f (f x), f (f (f x)), etc.

Based on comments in the module documentation, it appears that from_loop is the function I want:

"from_loop data next creates a (possibly infinite) lazy list from the successive results of applying next to data, then to the result, etc."

This description suggests that if I wanted a lazy list of non-negative integers, for example, I could define it like this:

let nat_nums = from_loop 0 (fun n -> n + 1)

However, this fails because the signature of from_loop is

'b -> ('b -> 'a * 'b) -> 'a LazyList.t

so the next function has signature ('b -> 'a * 'b). In utop, the error message underlines n + 1 and says

Error: This expression has type int but an expression was expected of type 'a * int

I don't understand what 'a is supposed to be. Why is the next function supposed to return a pair? Why is the type of the list supposed to be a 'a LazyList.t? Shouldn't the type of the elements be the same as the type of the argument to the next function? The description of the function doesn't make the answers clear to me.


In case it's helpful, my conception of what I'm trying to do comes from Clojure's iterate. In Clojure I could create the above definition like this:

(def nat-nums (iterate (fn [n] (+ n 1)) 0))

Solution

  • The function passed to from_loop has to return a pair. The first element of the pair is the value you want to return. The second element of the pair is the state required to calculate the next element later on.

    Your code:

    (fun n -> n + 1)
    

    Just calculates the next element of the lazy list, it doesn't return the state required for the next call. Something like this is what is wanted:

    (fun n -> (n, n + 1))
    

    (This will return a list starting with 0, which I think is what you want.)

    This formulation is more flexible than your clojure example, because it allows you to maintain arbitrary state distinct from the values returned. The state is of type 'b in the type you give for from_loop.

    I don't have Batteries right now, so I can't try this out. But I think it's correct based on the types.