How does one resolve F# Type Reference Errors?
Asked Answered
T

1

6

I've been through my books, and I've googled until I've ran out of search terms, yet I still can't find an example or answer to this problem:

The following code does not compile because the type Effect and the type Affect have not been declared at the time Entity is declared. So what I don't understand is how do to work around this.

In C++, this problem is solved via a prototype declaration in h files and then including the h file. In C# it is never an issue. So how is it resolved in F#?

#light
type Entity = 
    { 
        Name:string; 
        Affects:List<Affect>; //Compile error: The type Affect is not defined
        Effects:List<Effect>; //Compile error: the type Effect is not defined
    }

type Effect = 
    { 
        Name:string; 
        //A function pointer for a method that takes an Entity and returns an Entity
        ApplyEffect:Entity -> Entity;
    }

type Affect = 
    { 
        Name:string; 
        //A List of Effects that are applied by this Affect Object
        EffectList:List<Effect>; 
        //A function pointer to return an Entity modified by the listed Effects
        ApplyAffect:Entity->Entity;
    }

The underlying goal here is that an object of type Entity should be able to list the Affects it can apply to objects of Type Entity. Entity can also list the Effects that have been applied to it. This way the "current" state of an entity is found by folding all of the Effects against the original entity state.

Thank you for your time,

--Adam Lenda

Tagmemics answered 11/5, 2009 at 15:14 Comment(1)
See also #681106 which shows how to define mutually recursive functions as well as mutually recursive types.Ilbert
T
13

I believe this is the correct answer:

http://langexplr.blogspot.com/2008/02/defining-mutually-recursive-classes-in.html

so...

type Entity = 
    { 
        Name:string; 
        Affects:List<Affect>; 
        Effects:List<Effect>; 
    }
and Effect = 
    { 
        Name:string; 
        ApplyEffect:Entity -> Entity;
    }
and  Affect = 
    { 
        Name:string; 
        EffectList:List<Effect>; 
        ApplyAffect:Entity->Entity;
    }
Tagmemics answered 11/5, 2009 at 15:30 Comment(3)
Yup - that's just what I was about to post, now I'd found it. Chapter 8 in "Functional Programming for the Real World" :)Elite
chapter 3, pg 67 of 'expert f#'Algebraist
Hrmm... I was about to post the same thing, but concluded it wasn't possible after getting a compiler error! Turns out I just got the syntax slightly wrong.Electrochemistry

© 2022 - 2024 — McMap. All rights reserved.