BeginCheckWithIteratorメソッドの実装ですが、これは単純に、Actionを先頭から実行していってる。
CPSをモナドと見るならば、sequence_ と同じ。
sequence_ はfoldrで実装されているので、同じようにするならこう。
(ただし、無駄にややこしい)
EnumerableEx.cs
public static class EnumerableEx
{
public static TResult FoldRight<TSource, TResult>(this IEnumerable<TSource> source, TResult seed, Func<TSource, TResult, TResult> func)
{
Stack<TSource> stack = new Stack<TSource>(source);
foreach (TSource element in stack)
seed = func(element, seed);
return seed;
}
public static TResult FoldRightStrict<TSource, TResult>(this IEnumerable<TSource> source, TResult seed, Func<TSource, TResult, TResult> func)
{
var iter = source.GetEnumerator();
Func<TResult> rec = null;
rec = () => (iter.MoveNext())
? func(iter.Current, rec())
: seed;
return rec();
}
public static TResult FoldRightNonStrict<TSource, TResult>(this IEnumerable<TSource> source, TResult seed, Func<Func<TSource>, Func<TResult>, TResult> nonStrictFunc)
{
var iter = source.GetEnumerator();
Func<TResult> rec = null;
rec = () => (iter.MoveNext())
? nonStrictFunc(() => iter.Current, rec)
: seed;
return rec();
}
}
CPS.cs
public delegate void CPSAction(Action continuation);
public static class CPS
{
public static CPSAction Bind(this CPSAction m, Func<CPSAction> k)
{
return c => m(() => k()(c));
}
public static CPSAction Sequence_(this IEnumerable<CPSAction> source)
{
CPSAction seed = c => c();
Func<CPSAction, CPSAction, CPSAction> bindDiscard = (m, k) => m.Bind(() => k);
return source.FoldRight(seed, bindDiscard);
}
public static CPSAction NonStrictSequence_(this IEnumerable<CPSAction> source)
{
CPSAction seed = c => c();
Func<Func<CPSAction>, Func<CPSAction>, CPSAction> bindDiscard = (m, k) => m().Bind(() => k());
return source.FoldRightNonStrict(seed, bindDiscard);
}
}
で、こう呼び出す。
CheckIterator(onComplete).NonStrictSequence_()(() => { });