C#でfoldr
何か間違っている気がするなあ。
- (追記)戻り値のLazy
をやめて、Lazy は引数だけにしてみた。 - (追記)FoldRightに渡す関数の引数はどっちも遅延評価するようにした。ついでに、Lazy
じゃなくてFunc にしてみた。効果は同じ。
- (追記)FoldRightに渡す関数の引数はどっちも遅延評価するようにした。ついでに、Lazy
using System; using System.Collections.Generic; using System.Linq; class Program { static void Main(string[] args) { var source = InfiniteLoop(); var emptyList = Enumerable.Empty<int>(); var result = source.FoldRight(emptyList, LazyCons); var oneToTen = result.Skip(1).Take(10); var sum = oneToTen.FoldRight(0, LazyPlus); Console.WriteLine(sum); // 55 } static IEnumerable<int> InfiniteLoop() { for (var i = 0; ; i++) yield return i; } static IEnumerable<T> LazyCons<T>(Func<T> head, Func<IEnumerable<T>> tail) { yield return head(); foreach (var element in tail()) yield return element; } static int LazyPlus(Func<int> n, Func<int> m) { return n() + m(); } } public static class EnumerableEx { public static TResult FoldRight<TSource, TResult>(this IEnumerable<TSource> source, TResult seed, Func<Func<TSource>, Func<TResult>, TResult> lazyFunc) { // ちゃんとDisposeさせるのは面倒なので、今回はやらない。 return source.GetEnumerator().FoldRight(seed, lazyFunc); } public static TResult FoldRight<TSource, TResult>(this IEnumerator<TSource> source, TResult seed, Func<Func<TSource>, Func<TResult>, TResult> lazyFunc) { if (!source.MoveNext()) return seed; var head = source.Current; return lazyFunc(() => head, () => source.FoldRight(seed, lazyFunc)); } }