F#是否支持单独文件中的相互依赖的类?

Joh*_*zen 10 f# circular-dependency

我正在研究IronJS,我们的一个源文件变得越来越长.

现在,我正在努力让.NET互操作.我正在添加TryBinaryOperation方法,Undefined以便C#可以使用未定义值的JavaScript语义.

但是,这会引入对Operators类型的依赖,从而导致循环依赖.

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

...
Run Code Online (Sandbox Code Playgroud)

Operators.fs:

type Operators =
    ...
    // Here, we are referencing BoxedValue.
    static member add(BoxedValue l, BoxedValue r)
        ...
Run Code Online (Sandbox Code Playgroud)

所以,我们有这组依赖:
BoxedValue-> Undefined,Undefined-> BoxedValue,Undefined-> Operators,Operators-> BoxedValue

理想情况下,我们希望将每个文件拆分为自己的文件.

F#中是否可能存在跨文件循环依赖关系?

Tom*_*cek 6

没有直接的方法来编写在单独文件中定义的类型之间的循环依赖关系(在当前版本的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
Run Code Online (Sandbox Code Playgroud)

代码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)
Run Code Online (Sandbox Code Playgroud)

唯一棘手的事情是你需要确保在第一次使用类型Operators之前调用静态构造函数Undefined.这取决于您的具体情况,但通常有一些方法可以做到这一点.(可能有一些主要类型可以运行初始化)

  • 好的,所以我发现了我讨厌F#的唯一一件事.但是,我非常讨厌它,我再也不会用它做任何大事了. (3认同)