Kazurik
Kazurik

Reputation: 303

F# lookup issues on recursive types

I am trying to create two types where one is able to remove itself from the other such as in this example.

type employee (workplace : Job) =
    member this.Fire () = workplace.Employees.Remove(this) |> ignore
and Job () =
    let employees = new ResizeArray<employee>()
    member this.Employees = employees

But this gets me the compile error of "Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved."

I'm not sure what I am doing wrong here. Any help would be appreciated

Upvotes: 4

Views: 262

Answers (2)

Tomas Petricek
Tomas Petricek

Reputation: 243051

You can solve the problem even without reordering the declarations - when the F# compiler type-checks the Employee declaration, it doesn't yet know what is the type of workplace.Employees (because the type hasn't been declared yet), so it doesn't know where does the Remove method come from. You can correct that by adding type annotation that specifies that Employees is ResizeArray<Employee>:

type Employee (workplace : Job) =
    member this.Fire () = 
      let emps : ResizeArray<Employee> = workplace.Employees
      emps.Remove(this) |> ignore

and Job () =
    let employees = new ResizeArray<Employee>()
    member this.Employees = employees

However, this example isn't very functional - if you're going to use mutable state (such as ResizeArray), then the state should be hidden as private state of the type (so Jobs could have a Remove method).

In general, declaring recursive type declarations is a bit less comfortable in F# - however, you shouldn't need them that often. Quite frequently, you can use more generic types (i.e. Job may not need to know abou the Employee type).

Upvotes: 4

Semlar
Semlar

Reputation: 21

Try this..

type Job () =
    let employees = new ResizeArray<employee>()
    member this.Employees = employees
and employee (workplace : Job) =
    member this.Fire () = workplace.Employees.Remove(this) |> ignore

Upvotes: 2

Related Questions