Question

Is there a simpler Seq.unfold version that just takes the previous element as the state? I know you can easily adapt Seq.unfold to do that, but the result is not very readable.

Was it helpful?

Solution

I don't think there is a built-in function that does that.

Repeating the same pattern using Seq.unfold would be quite annoying, but you can easily use unfold to define a function that behaves as you want and then just use the new function:

module Seq = 
  let generate f v = 
    Seq.unfold (fun v -> let r = f v in Some(r, r)) v

As an aside, if I wanted to implement the pattern, I would probably go with a simple recursive sequence expression, which might be easier to read than using Seq.unfold. The generate function can be implemented like this:

let rec generate f v = seq {
  yield v
  yield! generate f (f v) }

This behaves a bit differently, because it yields the first value as well. Not sure what behaviour you want.

OTHER TIPS

Tomas' answer is good but, like you said, using Seq.unfold to do this is ugly, and, as he said, his generate function behaves differently.

If you want the same behavior as Seq.unfold, but using the previous element as state, this should do it:

let rec unfold f state = 
  seq {
    match f state with
    | Some x ->
      yield x
      yield! unfold f x
    | None -> ()
  }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top