Stream monad operation bind used both as a map and filter operation?

I want to create a stream monad with the return and bind operations

I tried the following:

module type STREAM_MONAD_SIG =
    type 'a stream 
    val return : 'a -> 'a stream 
    val bind : 'a stream  -> ('a -> 'b stream ) -> 'b stream 
    val (>>=) : 'a stream  -> ('a -> 'b stream ) -> 'b stream 
    val div5 : 'a stream -> 'a stream
module StMonad : STREAM_MONAD_SIG  = struct 
  type 'a stream = Nil | Cons of 'a * ( unit -> 'a stream)
  let return v = Cons(v, fun() -> Nil)
  let rec bind v f =
    match v with 
    | Nil -> Nil
    | Cons(h, t) -> 
        match f h with
        | Nil -> bind (t()) f
        | Cons(r_h, _) -> Cons(r_h, fun () -> bind (t()) f)
  let (>>=) = bind
  let div5 s1 = s1 >>= fun x -> if x mod 5 == 0 then return x else Nil
  let add2 s1 = s1 >>= fun x -> return (x+2)

My question is: Can this bind function be used both as a map and filter operation based on the type of f we pass? Filter application like div5, and add2 for map.

Example Input for div5:

open StMonad;;
let st = Cons(5, fun () -> Cons(6, fun () -> Cons(10, fun () -> Nil)));;
let res = div5 st;;

Output: Cons(5, Cons(10, fun () -> Nil)).

I think that your implementation of bind looks weird, more precisely you are abandoning the tail of the stream, which is a result of application of a function to the original head.

If your aim is to invent kanren-like stream monad, you need to merge two streams after invoking f h. In OCanren we use another primitive ‘mplus’ which does interleaved appending, and which is mutually recursive with bind. Look here for inspiration…