I’m working on IronJS, and one of our source files is getting very long.
Right now, I’m trying to get .NET interop working. I’m adding the TryBinaryOperation method to the Undefined so that C# can use the JavaScript semantics of the Undefined value.
However, this introduces a dependency on the Operators type, which causes a circular dependency.
Runtime.fs:
type BoxedValue() =
struct
// Contains IsUndefined and get_Undefined, referencing the Undefined class, below.
...
and type Undefined() =
inherit DynamicObject()
...
override x.TryBinaryOperation(binder:BinaryOperationBinder, arg:obj, result:obj byref) : bool =
// Here, we are referencing BoxedValue, above.
result <- Operators.add(Und, BoxedValue.Box(arg))
true
...
Operators.fs:
type Operators =
...
// Here, we are referencing BoxedValue.
static member add(BoxedValue l, BoxedValue r)
...
So, we have this set of dependencies:

Ideally, we would like to split each of these into its own file.
Is it possible in F# to have cross-file circular dependencies?
There is no direct way to write circular dependencies between types defined in separate files (in the current version of F#). In general, the way to solve the problem is to break one of the dependencies and allow some form of parameterization. Then you can fill the hole to build the circular reference later.
In your example, you can probably reasonably easily parameterize the
Undefinedtype to take the reference toOperatorsas a parameter. If you need more functions, then you can use an interface. For just a single function (likeOperators.add) you can write something like this:The code in
Operators.fswould provide the implementation:The only tricky thing is that you need to make sure that the static constructor of
Operatorswill get called before theUndefinedtype is used for the first time. This depends on your specific case, but there is usually some way to do that. (There is probably some main type that can run the initialization)