Tuesday, February 26, 2008

Defining mutually recursive classes in F#

While working in some F# code I learned that the definition of classes that refer to each other require a special syntax. For example, if you write the following code:


type Type1() =
class
let mutable m : Type2 Option = None
member this.foo(x : int) =
1
end

type Type2() =
class
let mutable m : Type1 Option = None
member this.goo() =
1
end


You will get a compiler error saying that: The type 'Type2' is not defined in the first use of Type2.

As explained in Adventures in F#--Corecursion defining mutually recursive functions requires the use of the and keyword between function definitions. As briefly mentioned in the Type Definitions section of the manual, the and keyword can also be used in types.

So the solution for defining the above example looks like this:


type Type1() =
class
let mutable m : Type2 Option = None
member this.foo(x : int) =
1
end
and Type2() =
class
let mutable m : Type1 Option = None
member this.goo() =
1
end


It is important to note that this syntax must be used also when mutual class references occur in method arguments or local definitions, for example:


type Type1() =
class
member this.foo(aType2 : Type2) =
1
end
and Type2() =
class
let mutable m : Type1 Option = None
member this.goo() =
1
end