2010-02-12 4 views
2

Je sais que je dois manquer quelque chose de vraiment évident ici. B.GetInstance().Call() génère l'erreur: Rechercher un objet de type indéterminé sur la base des informations antérieures à ce point de programme. Une annotation de type peut être nécessaire avant ce point de programme pour contraindre le type de l'objet. Cela peut permettre à la recherche d'être résolue.Inconnu besoin d'annotation de type ou de lancer

J'utilise v1.9.9.9.

type A() = 
    member x.Call() = B.GetInstance().Call() 

and B() = 
    static member GetInstance() = new B() 
    member x.Call() =() 

Je viens de découvrir que cela fonctionne: (B.GetInstance() :> B).Call()

Toute idée pourquoi le casting est nécessaire?

Répondre

7

Souvent, lorsque vous avez un ensemble récursif de méthodes dont les types doivent être déduits, F # a besoin d'aide. Une alternative plus agréable serait d'annoter la définition de B.GetInstance:

type A() = 
    member x.Call() = B.GetInstance().Call() 

and B() = 
    static member GetInstance() : B = new B() 
    member x.Call() =() 

Je crois que la raison pour laquelle vous rencontrez ce problème est que F # tente de résoudre tous les types inférées sur toutes les méthodes A et B en même temps (parce qu'ils sont définis comme des types mutuellement récursifs), ce qui engendre des problèmes, mais peut-être quelqu'un de l'équipe F # interviendra.

+0

Ce n'est pas intuitif de le comprendre. Sauvé ma journée, merci! – Cynede

7

Le résumé rapide est que dans un groupe récursif (par exemple des membres dans un type, ou des membres de types récursifs comme nous avons ici) F # lit les déclarations dans l'ordre de haut en bas de gauche à droite, suivi par le defi nitions dans l'ordre de haut en bas de gauche à droite. Donc dans ce cas, quand il atteint la définition de A.Call, il n'a pas encore lu la définition de B.GetInstance et ne sait donc pas (encore!) Que le type de retour de GetInstance sera B. La réponse de Keith le cloue pour cette situation, vous pouvez fournir une annotation de type pour spécifier le type de retour GetInstance dans sa déclaration.

Voir

Forcing F# type inference on generics and interfaces to stay loose

pour une profonde discussion sur ce qui se passe ici. Notez également que dans votre tentative initiale, vous n'avez pas besoin de "cast" (l'opération potentiellement dynamique, en utilisant :>), mais vous pouvez juste "annoter" (déclarer statiquement un type, en utilisant :) pour l'obtenir compiler. Mais il est plus logique de mettre l'annotation de type dans la déclaration de méthode pour GetInstance (en général, préférez les annotations supplémentaires aux signatures de méthodes au lieu de places arbitraires dans les corps).

+0

Bonne explication. Si je pouvais marquer deux réponses, je le ferais. – Daniel

Questions connexes