none
F# vs. Rx RRS feed

  • General discussion

  • I have spent the last two weeks learning F#. I was surprised to see that F# has 1st class language support for IObservable events and comes with a Core Library that mirrors some of the functionality of System.Reactive. For example Microsoft.FSharp.Control.Observable is the F# module that offers combinators that also exist in System.Reactive.Observable ...  (although some of the names differ) ... 

    On the other hand the parallel and asynchronous execution and synchronization and context switching functionality comes in F# in the form of Async workflows and the Microsoft.FSharp.Control.Async class. In a couple of ways the F# Async workflows remind me of Observable.Create() .. just a lot more powerful and with the extra level of ultra syntactic sugar to hide the continuation function passing . A rather funny thing is that the F# creators decided to re-brand monads with the term "workflow"... quite interesting is that F#'s Observable module does not offer (at least I have not seen it) a function similar to the Observable.Create() which is probably the "most functional feeling" part of Rx.

    As a newbie F# user I would really appreciate some insight from more experienced F# developers: How are F# asynchronous programming technique/libraries and the Reactive Extensions related to each other. For example when and why should I consider using functionality from System.Reactive from my F# code?

    And a slightly more more rhetorical question: Why has Microsoft two very similar static classes with many similar methods that differ only by their names (for example the F# Seq module and Enumerable)? For developers switching between languages this does definitely not simplify the job.

    After working with F# for a few days now my feelings are very mixed. On the one hand the type inference system and ultra-short definitions for almost everything are absolutely awesome - e.g. if you have never used F# before it certainly feels a little bit strange that the compiler infers from a type's usage whether it is an abstract base class or an interface etc. Closures, Continuation & Currying clearly are very powerful concepts - which beside of currying already made it into C# (which indeed has become a quite functional language). Immutable data types and Monads (workflows) of course are pretty cool concepts - although I have not yet a clear understanding on when using an immutable tree outperforms a mutable hashtable ... maybe some of the real benefits for functional programming will become apparent when the first thousand-core CPUs are around ;-)...

    Sorry for dropping some unordered thoughts about F# here in the Rx forum and talking a little bit off-topic. :) I am just a little bit confused whether F# is just a "VB for scientists" or my personal next favorite way to write (asynchronous/reactive) code for the .net platform. Certainly the most annoying trait of F# for me is that it derived from ML and unlike C# hides many .Net framework concepts because it was not build from scratch. OK - but at least one very practical language feature of F# is absolutely addictive and compensates for minor issues: Pattern matching

    What do you think?

    Sunday, May 2, 2010 8:47 PM

All replies

  • Welcome back Andreas!

    I would say that the main difference between the LINQ and F# approaches is that the LINQ sequence operators are tied to the LINQ query comprehension syntax while the F# workflow operators are tied to the F# expression syntax (which works wonderfully well).

    The names of the F# operators are typically closer to their FP roots, for instance "filter" instead of "Where", "map" instead of "Select" and "bind" instead of "SelectMany", and "zero" and "return".

    Also, because of the |> operator, F# prefers signatures with the receiver as the last argument.

    Wrt to first-class events (which implement IObservable<T>) and async workflows vs Rx, I see Rx as providing a common abstract interface that several concrete types that deal with concurrent and asynchronous computations can implement. Other examples include Task<T>, StreamInsight, and of course standard .NET events and the APM. This is analogous to LINQ-to-SQL and LINQ-to-Entities vs LINQ-to-Objects, or concrete types like T[], List<T>, ... vs the interface IEnumerable<T>. 

    Wrt to immutability etc I have a very fundamentalist point of view (http://www.youtube.com/watch?v=UuamC0T3hv8). If you do not abandon all effects and make them explicit in the type system, you might as well just enjoy the full benefits of side effects (like my favorite Rx constructs such as Subjects and SelectMany with a side-effecting selector function). For instance you can simulate a mutable cell using message passing and concurrency. Unchecked exceptions are very powerful side-effects as well. Note that this seems to be a minority viewpoint ;-) and the only language that I know of that takes this approach is Haskell.

    What you see happening however in the real world is that OO languages steal concepts from functional languages (C#, VB, Scala) and functional languages steal ideas from OO languages (F#, OCaml). The reason that these hybrid work is that the difference between closures/delegates and full-blown objects is very small, a closure is just an object with a single method. What Wikipedia says about mules:

    An aficionado of the mule claims that they are "more patient, sure-footed, hardy and long-lived than horses, and they are considered less obstinate, faster, and more intelligent than donkeys."

    seems to be true about mixed functional-OO as well. The great thing about .NET is that everybody can pick the language they feel most comfortable with.

    Tuesday, May 4, 2010 4:55 AM
  • Hi Erik,

    thanks for the amusing answer - I really enjoyed watching your OSCON keynote session!

    However I wonder how a pure functional language would interact with the .net FX OO ecosystem - would every call to an instance- or class-function return a monad type instead of the actual return value? I am a rather functional noob so please correct me if I got it wrong but as far as I understand it programs written in a pure functional language like Haskell (beside those producing a constant output) are finally io-monad-driven ... e.g. a pure program returns an IO monad. The outer system then starts "evaluating" the "wrapped operations" switching between impure (OS functions) for IO and pure functions to continue the execution.

    Two questions Regarding Rx/IObservable & F#:

    1. Was IObservable first introduced by Rx or was it first part of earlier F# releases? I somewhere read that earlier releases of F# came with their own IObservable version as part of the core library.

    2. Will future Rx innovations also be provided as new function of the F# Observable module? Is the Rx team also responsible for the F# Observable module?


    Andreas

     

    Tuesday, May 4, 2010 4:46 PM
  • We started working on IObservable/IObserver a long time ago when we were trying to make asynchronous calls that arose from tier-splitting palatable. Initially we used just the continuation monad but then discovered the beautiful duality with IEnumerable and IEnumerator.

    F# used to have its own type for first class events (http://blogs.msdn.com/dsyme/archive/2006/03/24/559582.aspx), and they were one of the first groups to adopt IObservable.

    Interop between Haskell and the impure world does put msot foreign calls into the IO monad, as it should http://research.microsoft.com/en-us/um/people/emeijer/papers/heavenhell.pdf. As I may say, it is rather elegant.

    Hope this helps.

    Wednesday, May 5, 2010 5:22 AM
  • Tomas Petricek recently noted one key difference in Async and Rx: Rx is a push model over sequences whereas Async is closer to Task in that it works over only one value at a time. His implementation of AsyncSeq is closer to Rx except that it is still a pull model. The observables available in the F# library are targeted primarily at better interop with F# types and aren't the same as the Rx library. Steffen Forkmann and I have worked on a wrapper library to bring Rx into F# called FSharp.Reactive. It adds a number of missing pieces, but there are some caveats. You'll find that an ObservableBuilder monad is rather difficult to achieve.
    Ryan Riley @panesofglass
    Sunday, September 11, 2011 10:40 PM