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

F# F中不同文件的类型和函数之间存在循环依赖性问题#,f#,cyclic,F#,Cyclic,我当前的项目使用具有40种不同类型(描述的联合)的AST,并且该AST中的几个类型具有循环依赖性。 类型不是那么大,因此我将它们放在一个文件中并应用type。。。和…相互依赖类型的构造 现在,我正在添加函数,以便在AST中的每个元素下进行一些计算。 因为有很多函数都有几行代码,为了使源代码更清晰易读,我将这些函数分离在不同的文件中 它在缺少循环依赖项的情况下是正常的,在依赖函数位于同一个文件中时也是有效的-在这种情况下,我可以使用let rec function1。。。和功能2…构造 但这对我来

我当前的项目使用具有40种不同类型(描述的联合)的AST,并且该AST中的几个类型具有循环依赖性。 类型不是那么大,因此我将它们放在一个文件中并应用
type。。。和…
相互依赖类型的构造

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

它在缺少循环依赖项的情况下是正常的,在依赖函数位于同一个文件中时也是有效的-在这种情况下,我可以使用
let rec function1。。。和功能2…
构造

但这对我来说是行不通的

我也不正确地认为签名文件可以帮助我,但是他们的行为和C++不同。 -它们用于定义函数/类型访问模式(内部/公共),也可以在此处添加函数/类型注释标题

我看到的唯一可能的解决方案是将所有函数移到一个文件中,并使用
let rec。。。而且。。。而且。。。而且。。。和…
构造

可能有人有不同的想法吗?


提前感谢。

如评论中所述,无法在多个文件之间拆分具有循环依赖关系的函数(或类型)。签名文件主要用于文档目的,因此不会有帮助

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

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

总之,这些只是一些通用的技术。如果不了解更多关于你工作的类型,就很难给出更精确的建议。如果您可以分享更多详细信息,也许我们可以找到一种避免某些递归引用的方法。

根据此答案,不可能将依赖函数拆分为多个文件:感谢链接-是的,我了解到这是不可能的,但认为有人知道解决方法谢谢,这正是我想要的——作为一个例子,我必须解析并计算以下表达式:“如果(c>0)那么1+(a[(b>0)?b*2-1:0]+1)*b else 2”。在这个例子中有几个循环依赖关系:c可以是表达式,数组a可以有几个谓词,索引也可以作为表达式计算,算术计算中的括号也可以使用递归,等等。顺便说一句,好书-它在理解F方面帮了我很多#