Iterating streams

Hi, i’ve been trying to create a program that reads the lines from a file, formats them a certain way and then prints them out. Here is what my main looks like:

let () =
  In_channel.create (Sys.get_argv()).(1)
  |> extract
  |> iter_stream ~f:(fun (f,c,l) -> printf " %s %s %s \n" f c l" )

My extract function has this type:

val extract: In_channel -> (string*string*string) stream

The problem i’m running into is that creating this function:

let rec iter_stream st ~f = 
val iter_stream: 'a stream -> ('a -> unit) -> unit

I had no trouble with creating a stream and formating the lines inside of it but when it comes to iterating it and ~f i just get lost.

Labelled arguments must be exposed in the function signature.
A function defined like this:

let rec iter_stream st ~f = 

Has a signature like this (note the f: part):

val iter_stream: 'a stream -> f:('a -> unit) -> unit

I looked around and this is what i’m able to come up with although it does give me a type error

let rec iter_stream st ~f =
  match st with 
  | None -> ()
  | Some( x, st') -> f x ; iter_stream st' ~f

I’d like to know if this is at least a step in the right direction.

It seems you are trying to use stream as if it was defined like this:

type 'a stream = ('a * 'a stream) option

But I suspect that it isn’t right because this would be equivalent to list

Is stream defined like this ?

type 'a stream = unit -> ('a * 'a stream) option

In this case st would be a function to call like this: st ().

But this definition requires the -rectypes option, I suspect that stream may not be defined like this at all but that it declares new constructors like Seq does: https://caml.inria.fr/pub/docs/manual-ocaml/libref/Seq.html

This is what i’m required to use:

type 'a stream = Nil | Cons of 'a * 'a stream thunk and 'a thunk = unit -> 'a

In my case, st is the stream that gets created after calling the extract function.

type 'a stream = Nil | Cons of 'a * 'a stream thunk and 'a thunk = unit -> 'a

is the same as

type 'a thunk = unit -> 'a
type 'a stream = Nil | Cons of 'a * 'a stream thunk

which is the same as (substituting 'a stream thunk using the definition of thunk)

type 'a stream = Nil | Cons of 'a * (unit -> 'a stream)

So this comment is correct:

But there’s another problem:

match st with
| None -> ...
| Some ...

assumes st is of type 'a option as it is matching against the constructors of the option type (Some and None).

You have a 'a stream. 'a stream’s constructors are Nil and Cons.

I see, it didn’t make any sense to use None and Some indeed.

Cons(x, st') -> f x; stream_iter st' ~f

Regarding the second point, even if i match the stream with Cons (x, st'), i can’t pass the st' as the argument to the recursive function since st' is not a stream. Looking at the type definition st' in this case is of type a' stream thunk. How can i get a' stream type to pass it as argument.