F#中不同文件的类型和函数之间的循环依赖问题

Posted

技术标签:

【中文标题】F#中不同文件的类型和函数之间的循环依赖问题【英文标题】:Problem with cyclic dependencies between types and functions from different files in F# 【发布时间】:2011-07-21 06:09:16 【问题描述】:

我当前的项目使用具有 40 种不同类型(可区分联合)的 AST,并且该 AST 中的几种类型具有循环依赖关系。 类型不是很大,因此我将它们放在一个文件中,并为相互依赖的类型应用了type ... and ... 构造。

现在,我正在添加函数以在 AST 中的每个元素下进行一些计算。 因为函数很多,里面有几行代码,为了让源代码更清晰易读,我把这些函数分开放在不同的文件中。

在没有循环依赖的情况下没关系,当依赖函数在同一个文件中时也可以 - 在这种情况下我可以使用let rec function1 ... and function2 ... 构造。

但它不适用于我的情况。

另外,我错误地认为签名文件可以帮助我解决这个问题,但它们的行为与 C++ 不同

它们用于定义函数/类型访问模式(内部/公共),也可以在此处添加函数/类型注释头。

我看到的唯一可能的解决方案是将所有函数移动到一个文件并使用let rec ... and ... and ... and ... and ... 构造。

可能有人有不同的想法?

【问题讨论】:

根据此答案,无法跨文件拆分依赖函数:***.com/questions/5396465/… 感谢您的链接 - 是的,我读到这是不可能的,但认为有人知道一个聪明的解决方法 【参考方案1】:

正如 cmets 中提到的,没有办法在多个文件之间拆分具有循环依赖关系的函数(或类型)。签名文件主要用于文档目的,因此它们无济于事。

如果不知道依赖项到底是什么,就很难给出一些建议。但是,可以使用函数或接口重构实现的某些部分。例如,如果您有:

let rec process1 (a:T1) = 
  match a with
  | Leaf -> 0
  | T2Thing(b) -> process2 b

and process2 (b:T2) = 
  match b with 
  | T1Thing(a) -> process1 a

您可以修改函数process1 以将第二个函数作为参数。这使得在两个文件之间拆分实现成为可能,因为它们不再相互递归:

// File1.fs
let process1 (a:T1) process2 = 
  match a with
  | Leaf -> 0
  | T2Thing(b) -> process2 b

// File2.fs
let rec process2 (b:T2) = 
  match b with 
  | T1Thing(a) -> process1 a process2

如果你能找到一些更清晰的结构 - 例如两个函数块,包含逻辑相关的函数,需要互相访问,那么也可以定义一个接口。这对于只有两个函数的示例没有多大意义,但它看起来像这样:

type IProcess2 = 
  abstract Process : T2 -> int

let process1 (a:T1) (process2:IProcess2) = 
  match a with
  | Leaf -> 0
  | T2Thing(b) -> process2.Process b

let rec process2 (b:T2) = 
  let process2i = 
     new IProcess2 with 
        member x.Process(a) = process2 a 
  match b with 
  | T1Thing(a) -> 
    process1 a process2i

无论如何,这些只是一些通用技术。如果不了解您正在使用的类型的更多信息,很难给出更准确的建议。如果您可以分享更多详细信息,也许我们可以找到一种方法来避免一些递归引用。

【讨论】:

谢谢,这正是我要找的 - 作为一个例子,我必须解析和计算以下 Expression: "if (c > 0) then 1 + (a[(b > 0) ? b * 2 - 1 : 0] + 1) * b else 2"。在这个例子中有几个循环依赖:c 可以是一个 Expression,数组 a 可以有多个谓词,索引也计算为 Expression,算术计算中的括号也可以使用递归等。顺便说一句,好书 - 它对我理解 F# 有很大帮助

以上是关于F#中不同文件的类型和函数之间的循环依赖问题的主要内容,如果未能解决你的问题,请参考以下文章

头文件之间的循环依赖

如何解决 Maven 中的循环依赖?

解决由于类之间的循环依赖而导致的构建错误

解决由于类之间的循环依赖而导致的构建错误

解决由于类之间的循环依赖而导致的构建错误

解决由于类之间的循环依赖而导致的构建错误