I know I must be missing something really obvious here. B.GetInstance().Call()
generates the error: Lookup on object of indeterminate type based on information
Frequently when you've got a recursive set of methods whose types to infer, F# needs help. A more pleasant alternative would be to annotate the definition of B.GetInstance
:
type A() =
member x.Call() = B.GetInstance().Call()
and B() =
static member GetInstance() : B = new B()
member x.Call() = ()
I believe that the reason you run into this problem is that F# tries to solve all inferred types on all methods in A and B simultaneously (because they are defined as mutually recursive types), and this leads to problems, but perhaps someone from the F# team will weigh in.
The quick summary is that in a recursive group (e.g. members in one type, or members of recursive types like we have here) F# reads the declarations in left-to-right top-to-bottom order, followed by the definitions in left-to-right top-to-bottom order. So in this instance when it reaches the definition of A.Call
, it has not yet read the definition of B.GetInstance
and therefore does not (yet!) know that the return type of GetInstance
will be B
.
Keith's answer nails it for this situation, you can provide a type annotation to specify the return type of GetInstance
in its declaration.
See
Forcing F# type inference on generics and interfaces to stay loose
for a deep discussion of what's going on here.
Note also that in your original attempt, you don't need to "cast" (the potentially dynamic operation, using :>
), instead you can just "annotate" (statically declare a type, using :
) to get it to compile. But makes more sense to put the type annotation in the method declaration for GetInstance
(generally, prefer addition annotations to method signatures instead of arbitrary places inside bodies).