The venerable Oleg Kiselyov once posted about the "best" collection traversal API. Let's call this ideal iterator a "SuperFold". LTU also covered his article. Essentially, a SuperFold is a left fold with early termination support. Any cursor can then be automatically derived from the SuperFold. The converse is not true.
Additional arguments are made in the above paper and in the LTU thread, so I won't repeat them here. Without further ado, I present the SuperFold for my purely functional list in C#:
While quite simple, it's not as efficient as it should be since C#/.NET doesn't support proper tail calls. You can see in that source file that I derived FoldLeftDerived from SuperFold. Deriving FoldRight is a bit trickier, so I have to think about it. The simple, inefficient, answer is to simply reverse the list.
I've also enhanced the FP# library with:
[1] It's very frustrating to see how close MS gets to a truly general and useful abstraction, only to lock it down for no apparent reason. What good reason is there for Nullable to be restricted to struct types? If you give it more than a second's thought, I think you'll realize that there is no good reason. Nullable is the option type if it weren't for this restriction!
Additional arguments are made in the above paper and in the LTU thread, so I won't repeat them here. Without further ado, I present the SuperFold for my purely functional list in C#:
//OCaml signature: ((T → B → bool * B) → B → B) → (T → B → bool * B) → B → B
B SuperFold<B>(
Fun<Fun<T, B, Pair<bool, B>>, B, B> self,
Fun<T, B, Pair<bool, B>> proc,
B seed)
{
bool cont;
proc(head, seed).Bind(out cont, out seed);
return cont ? self(proc, seed) : seed;
}
While quite simple, it's not as efficient as it should be since C#/.NET doesn't support proper tail calls. You can see in that source file that I derived FoldLeftDerived from SuperFold. Deriving FoldRight is a bit trickier, so I have to think about it. The simple, inefficient, answer is to simply reverse the list.
I've also enhanced the FP# library with:
- A number of tuple types (up to 10),
- Tuple inference,just call: Tuple._(a,b,c,...)
- streamed versions of Map/Filter/FoldRight over IEnumerable which don't build intermediate lists,
- FoldLeft over IEnumerable including support for early termination,
- FoldLeft over my purely functional list including support for early termination,
- Option type now looks more like System.Nullable, with an overload for the | operator to choose between an empty option, or a default value [1],
- Partial application for almost all defined function types
[1] It's very frustrating to see how close MS gets to a truly general and useful abstraction, only to lock it down for no apparent reason. What good reason is there for Nullable to be restricted to struct types? If you give it more than a second's thought, I think you'll realize that there is no good reason. Nullable is the option type if it weren't for this restriction!
Comments
2. I think there is no iterative equivalent of SuperFold, due to the mutual recursion between self and proc.