Kei*_*ith 6 f# mutual-recursion
我可以使用and关键字来设置相互递归的函数定义.我也可以and用于相互递归的类型,但是如果类型和函数之间存在相互递归的关系呢?我唯一的选择是使该功能成为该类型的成员,还是我可以使用类似的东西and?
编辑:添加一个简化的伪示例,我希望说明我正在尝试做什么
// A machine instruction type
type Instruction = Add | CallMethod int (* method ID *) | ...
// A class representing a method definition
type MethodDef (fileName : string) =
member x.Params with get () = ...
member x.Body with get() =
let insts = readInstructions fileName
Array.map toAbstractInst insts
// a more abstract view of the instructions
and AbstractInstruction = AbstAdd | AbstCallMethod MethodDef | ...
// a function that can transform an instruction into its abstract form
let toAbstractInst = function
| Add -> AbstAdd
| CallMethod methodId -> AbstCallMethod (somehowResolveId methodId)
| ...
Run Code Online (Sandbox Code Playgroud)
所以你可以在这里看到递归关系是间接设置的:MethodDef < - > AbstractInst AND MethodDef - > toAbstractInst - > AbstractInstruction(其中 - >表示"取决于")
Tom*_*cek 10
没有例子,这个问题很难回答
如果你有没有成员的相互递归类型,那么类型不需要知道函数(所以你可以先定义类型然后定义函数).
如果你有具有成员函数的相互递归类型,那么成员可以看到彼此(跨类型)你应该没问题
唯一棘手的情况是,当你有相互递归的类型,相互递归的函数,并且你也希望将一些函数公开为成员.然后你可以使用类型扩展:
// Declare mutually recursive types 'A' and 'B'
type A(parent:option<B>) =
member x.Parent = parent
and B(parent:option<A>) =
member x.Parent = parent
// Declare mutually recursive functions 'countA' and 'countB'
let rec countA (a:A) =
match a.Parent with None -> 0 | Some b -> (countB b) + 1
and countB (b:B) =
match b.Parent with None -> 0 | Some a -> (countA a) + 1
// Add the two functions as members of the types
type A with
member x.Count = countA x
type B with
member x.Count = countB x
Run Code Online (Sandbox Code Playgroud)
在这种情况下,你可以只让countA和countB两种类型的成员,因为它会更容易,但如果你有,你想要写为功能更复杂的代码,那么这是一个选项.
如果所有内容都写在一个模块中(在单个文件中),那么F#编译器将类型扩展编译为标准实例成员(因此它看起来就像从C#角度看的普通类型).如果在单独的模块中声明扩展,那么它们将被编译为F#特定的扩展方法.