Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best approach for designing F# libraries for use from both F# and C#

Tags:

c#

f#

People also ask

Why is the F-layout good?

F-shaped pattern will help you create a design with good visual hierarchy, a design that people can scan easily. F-shaped layout feels comfortable for the most western readers, because they have been reading top to bottom, left to right for their entire lives.

What is the F-pattern layout?

The F-Pattern is a simple layout designed to guide a user's eye to information that you want them to see based on engrained human behavior. In this case, the F-pattern is rooted in the way we read — left to right.

What is F type style in web designing?

The F-Shaped Pattern. In the F-shaped scanning pattern is characterized by many fixations concentrated at the top and the left side of the page. Specifically: Users first read in a horizontal movement, usually across the upper part of the content area.

What is F and Z-pattern in design?

While the F-Layout tends to be more appropriate for pages dense with content, the Z-Layout is primarily meant for pages with minimal copy. Essentially, the Z-Pattern is better suited for pages where simplicity is a priority and the main takeaway is the CTA.


Daniel already explained how to define a C#-friendly version of the F# function that you wrote, so I'll add some higher-level comments. First of all, you should read the F# Component Design Guidelines (referenced already by gradbot). This is a document that explains how to design F# and .NET libraries using F# and it should answer many of your questions.

When using F#, there are basically two kinds of libraries you can write:

  • F# library is designed to be used only from F#, so it's public interface is written in a functional style (using F# function types, tuples, discriminated unions etc.)

  • .NET library is designed to be used from any .NET language (including C# and F#) and it typically follows .NET object-oriented style. This means that you'll expose most of the functionality as classes with method (and sometimes extension methods or static methods, but mostly the code should be written in the OO design).

In your question, you're asking how to expose function composition as a .NET library, but I think that functions like your compose are too low level concepts from the .NET library point of view. You can expose them as methods working with Func and Action, but that probably isn't how you would design a normal .NET library in the first place (perhaps you'd use the Builder pattern instead or something like that).

In some cases (i.e. when designing numerical libraries that do not really fit well with the .NET library style), it makes a good sense to design a library that mixes both F# and .NET styles in a single library. The best way to do this is to have normal F# (or normal .NET) API and then provide wrappers for natural use in the other style. The wrappers can be in a separate namespace (like MyLibrary.FSharp and MyLibrary).

In your example, you could leave the F# implementation in MyLibrary.FSharp and then add .NET (C#-friendly) wrappers (similar to code that Daniel posted) in the MyLibrary namespace as static method of some class. But again, .NET library would probably have more specific API than function composition.


You only have to wrap function values (partially-applied functions, etc) with Func or Action, the rest are converted automatically. For example:

type A(arg) =
  member x.Invoke(f: Func<_,_>) = f.Invoke(arg)

let a = A(1)
a.Invoke(fun i -> i + 1)

So it makes sense to use Func/Action where applicable. Does this eliminate your concerns? I think your proposed solutions are overly-complicated. You can write your entire library in F# and use it pain-free from F# and C# (I do it all the time).

Also, F# is more flexible than C# in terms of interoperability so it's generally best to follow traditional .NET style when this is a concern.

EDIT

The work required to make two public interfaces in separate namespaces, I think, is only warranted when they are complementary or the F# functionality is not usable from C# (such as inlined functions, which depend on F#-specific metadata).

Taking your points in turn:

  1. Module + let bindings and constructor-less type + static members appear exactly the same in C#, so go with modules if you can. You can use CompiledNameAttribute to give members C#-friendly names.

  2. I may be wrong, but my guess is that the Component Guidelines were written prior to System.Tuple being added to the framework. (In earlier versions F# defined it's own tuple type.) It's since become more acceptable to use Tuple in a public interface for trivial types.

  3. This is where I think you have do things the C# way because F# plays well with Task but C# doesn't play well with Async. You can use async internally then call Async.StartAsTask before returning from a public method.

  4. Embrace of null may be the single biggest drawback when developing an API for use from C#. In the past, I tried all kinds of tricks to avoid considering null in internal F# code but, in the end, it was best to mark types with public constructors with [<AllowNullLiteral>] and check args for null. It's no worse than C# in this respect.

  5. Discriminated unions are generally compiled to class hierarchies but always have a relatively friendly representation in C#. I would say, mark them with [<AllowNullLiteral>] and use them.

  6. Curried functions produce function values, which shouldn't be used.

  7. I found it was better to embrace null than to depend on it being caught at the public interface and ignore it internally. YMMV.

  8. It makes a lot of sense to use list/map/set internally. They can all be exposed through the public interface as IEnumerable<_>. Also, seq, dict, and Seq.readonly are frequently useful.

  9. See #6.

Which strategy you take depends on the type and size of your library but, in my experience, finding the sweet spot between F# and C# required less work—in the long run—than creating separate APIs.


Although it probably would be an overkill, you could consider writing an application using Mono.Cecil (it has awesome support on the mailing list) that would automate the conversion on the IL level. For example, you implement your assembly in F#, using the F#-style public API, then the tool would generate a C#-friendly wrapper over it.

For instance, in F# you would obviously use option<'T> (None, specifically) instead of using null like in C#. Writing a wrapper generator for this scenario should be fairly easy: the wrapper method would invoke the original method: if it's return value was Some x, then return x, otherwise return null.

You would need to handle the case when T is a value type, i.e. non-nullable; you would have to wrap the return value of the wrapper method into Nullable<T>, which makes it a bit painful.

Again, I'm quite certain that it would pay off to write such a tool in your scenario, maybe except if you'll be working on this such library (usable seamlessly from F# and C# both) regularly. In any case, I think it would be an interesting experiment, one that I might even explore sometime.


Draft F# Component Design Guidelines (August 2010)

Overview This document looks at some of the issues related to F# component design and coding. In particular, it covers:

  • Guidelines for designing “vanilla” .NET libraries for use from any .NET language.
  • Guidelines for F#-to-F# libraries and F# implementation code.
  • Suggestions on coding conventions for F# implementation code