Не существует прямого способа записи циклических зависимостей между типами, определенными в отдельных файлах (в текущей версии F #). В общем случае, способ решить проблему - это сломать одну из зависимостей и разрешить некоторую форму параметризации. Затем вы можете заполнить отверстие, чтобы построить круговую привязку позже.
В вашем примере вы, вероятно, можете достаточно легко параметризовать тип Undefined
, чтобы взять ссылку на Operators
в качестве параметра. Если вам нужно больше функций, то вы можете использовать интерфейс. Только для одной функции (например, Operators.add
) вы можете написать что-то вроде этого:
and type Undefined() =
inherit DynamicObject()
...
// To be specified by code defined later
// (this can either be a function or an interface implementation)
static let mutable addition = (fun x y -> failwith "not initialized")
static member SetAddition(f) = addition <- f
override x.TryBinaryOperation
(binder:BinaryOperationBinder, arg:obj, result:obj byref) : bool =
// Here, we are referencing BoxedValue, above.
result <- addition(Und, BoxedValue.Box(arg))
true
Код в Operators.fs
будет обеспечивать реализацию:
type Operators =
...
// Static constructor of the `Operators` type
static do Undefined.SetAddition(Operators.add)
....
// Here, we are referencing BoxedValue.
static member add(BoxedValue l, BoxedValue r)
Единственная сложность заключается в том, что вам нужно убедиться, что статический конструктор Operators
будет вызван до того, как тип Undefined
будет использован впервые. Это зависит от вашего конкретного случая, но обычно есть какой-то способ сделать это. (Вероятно, есть некоторый основной тип, который может запустить инициализацию)