In Haskell, Iteratee based I/O seems very attractive. Iteratees are a composable, safe, fast ways of doing I/O inspired by the 'fold' a.k.a. 'reduce' function in functional languages. Basically, if you have a traversal the idea is开发者_如何转开发 to encapsulate the traversal state into a so-called "enumerator" who calls the "iteratee" which is in turn a function either returning a value or a request for more data along with a continuation for the enumerator to call. So only the enumerator knows the state of the traversal while the iteratee knows what to do with the data and builds values out of it. The nice thing about it is that iteratees are automatically composable, where output of one iteratee is fed to another to make a bigger one.
So, two questions:
- Does the concept even make sence in other languages, like plain object oriented languages or is it only useful for overcoming the shortcomings of Haskell's lazy I/O?
- Are there any actual implementations for other languages, especially C# (as that is what my company uses)? (A google search turns up one mention of iteratees in Scala; well, I'm not that interested in Scala right now).
If I understand what you're describing, it sounds an awful lot like the Reactive Extensions:
http://channel9.msdn.com/Tags/reactive+extensions
Erik Meijer explains how IObservable is the mathematical dual of IEnumerable here:
http://channel9.msdn.com/Shows/Going+Deep/Expert-to-Expert-Brian-Beckman-and-Erik-Meijer-Inside-the-NET-Reactive-Framework-Rx
First of all, realize that Haskell's "Lazy IO" is kind of a hack that breaks purity in a limited way to allow I/O to occur on demand as data is consumed lazily. This is business as usual in an impure language, and lazy sequences can create the same problem anywhere. So if you're doing something like, say, exposing an IEnumerable
interface to a file and reading it incrementally as the sequence is enumerated, this isn't really any different.
Second, iteratees and enumerators can also be composed into what are called (in somewhat clumsy fashion) enumeratees. At this point you have something being fed sequential data, producing incremental results as they're ready, and feeding those results to something else. This is basically a variety of stream processor, a concept which probably predates both Haskell and C# by a considerable margin.
Third, iteratees are an encapsulation of abstracted behavior, with their internal workings hidden. This is arguably more in keeping with OO principles than with ML-style functional programming, at least in the sense of "OO principles" that are espoused by the people who yell at you for using getters and setters and think control flow should be implemented via polymorphism.
Given the above, I'd say that the iteratee concept would fit just fine in C#, and would be most naturally implemented as a sort of inverted equivalent of IEnumerable
, with compositional data-flow objects and a "push" interface rather than the standard LINQ's "pull" style.
精彩评论