A little explanation before I ask the question. I have a sequence on which I want to perform a number of fold operations. But evaluating the sequence is slow and expensive (it's iterating through a database) and (though it's not explicit here) I want to provide progressive output to the user. So I'd really like to do all the folds in one go. Something like:
theSeq |> Seq.CoFold [ line (folder1, initAcc1, action1) line (folder2, initAcc2, action2) ] the action being something that's done with the accumulator once the fold is complete. I'd use it something like this:
theSeq |> Seq.CoFold [ line ((fun acc r -> acc+1), 0, (fun d -> printfn "%A" d)) // counter line ((fun acc r -> acc.Add(r), Set.empty, whatever) // uniques ] I've worked out that whatever line is, it should be genericked based on the type of theSeq, but it shouldn't depend on the type of initAcc, or the type of the folder function itself. So, I've come up with the following (which doesn't work):
module Seq = type 'T line (f:'State -> 'T -> 'State, a:'State, cb:'State->unit) = let s = ref a member x.incr (j:'T) = s := f !s j member x.cb = cb !s let CoFold (folders: 'T line list) (jj: 'T seq) = for j in jj do folders |> List.iter (fun o -> o.incr j) folders |> List.iter (fun o -> o.cb) The problem with this is that it wants to generic line based on both 'T and 'State, and that means that the two lines I've shown above are incompatible with each other, even though neither ever exposes the type of acc.
I've tried several other approaches (e.g. making line into a discriminated union, making line into an abstract base class, and more), and in every case I run into some other manifestation of the original problem. I'm really at a loss to know where to look next.
This doesn't feel like it should be a difficult problem, but I guess I've got a blind spot somewhere. Any hints gratefully received.
Thanks