Ответ 1
Нет прямого способа записи круговых зависимостей между типами, определенными в отдельных файлах (в текущей версии 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
будет использоваться в первый раз. Это зависит от вашего конкретного случая, но обычно есть способ сделать это. (Вероятно, существует некоторый основной тип, который может запускать инициализацию)