1) Is this architecture advisable?
It certainly isn't a bad approach :)
The main thing I'd be worried about is how it affects other members of the team -- will they need to learn a new language to add new functionality or debug problems? If the rest of your team isn't comfortable using it, you might want to consider looking for or building your own message passing library in C#.
2) If so, are there any examples out
there that demonstrate a best
practices approach to this design?
I like to mix F# and C# in my projects all the time. In my own experience, leveraging C# dlls from F# is much easier than the other way around. Most of the constructs we like to use in F# look funny and unintuitive in C#. Just for funsies, see how the following code renders in Reflector:
let f x y z = x(y z)
let (|A|B|C|) x =
match x with
| 1 -> A
| 2 -> B
| x -> C x
type whatever = X | Y | Z of int
Curried functions render as an FSharpFunc
, active patterns have a funny name and return type, unions have a very strange set of members, etc. They look weird in C#, so you'll very likely want to expose a facade with nicer C# signature for any modules you expect to be consumed publically. For example:
module CSharpFacade =
let f(x : System.Func<_, _>, y : System.Func<_, _>, z) = f (fun param -> x.Invoke(param)) (fun param -> y.Invoke(param)) z
[<AbstractClass>]
type Whatever() =
inherit obj()
abstract member Map : unit -> whatever
type X() =
inherit Whatever()
override this.Map() = whatever.X
type Y() =
inherit Whatever()
override this.Map() = whatever.Y
type Z(value : int) =
inherit Whatever()
member this.Value = value
override this.Map() = whatever.Z(value)
So its pretty straight forward to wrap up F# delegates and unions for C#. I don't really care to expose the active pattern, its going to be internal unless otherwise needed.
And you might want to wrap Some/None types in something more palatable, such as using Nullable<someValueType>
in place of Option<someValueType>
, and mapping a null
reference type to None
where needed, etc.