2010-10-04 6 views
2

J'ai un type qui implémente l'interface IEnumerable<T>, tout est ok:Est-ce un bug F #?

open System 

type Bar() = 

    interface Collections.IEnumerable with 
     member x.GetEnumerator() = null 

    interface Collections.Generic.IEnumerable<int> with 
     member x.GetEnumerator() = null 

Mais les choses se passe mal si le type hérite implémentation de l'interface IEnumerable via le type de base:

open System 

type Foo() = 
    interface Collections.IEnumerable with 
     member x.GetEnumerator() = null 

type Bar() = 
    inherit Foo() 

    interface Collections.Generic.IEnumerable<int> with 
     member x.GetEnumerator() = null 
code

produit au-dessus du type erreurs d'inférence:

  • The member 'GetEnumerator<'a0 when 'a0 : null> : unit -> 'a0 when 'a0 : null' does not have the correct type to override any given virtual method

  • The member 'GetEnumerator<'a0 when 'a0 : null> : unit -> 'a0 when 'a0 : null' does not have the correct number of method type parameters. The required signature is 'GetEnumerator : unit -> Collections.Generic.IEnumerator<int>'.

Ai-je fait quelque chose de mal ou c'est un F bug # compilateur?

Microsoft (R) F# 2.0 Interactive build 4.0.30319.1


Mise à jour exemple plus canonique:

type IFoo  = abstract Bar : obj list 
type IFoo<'a> = abstract Bar : 'a list 
       inherit IFoo 
/* ok */ 
type Foo  = interface IFoo  with member x.Bar = [] 
        interface IFoo<Foo> with member x.Bar = [] 
/* fail */ 
type FooBase = interface IFoo  with member x.Bar = [] 
type FooDerived = interface IFoo<Foo> with member x.Bar = [] // <--- 
        inherit FooBase 
/* 
error FS0017: The member 'get_Bar : unit -> 'a list' does not 
    have the correct type to override any given virtual method. 
*/ 
+0

Pouvez-vous poster votre code actuel? – Gabe

Répondre

2

Ce n'est pas un bug, cela est juste une inférence de type échouent en raison de F # peut mettre en œuvre des éléments d'interface hérités dans la déclaration de mise en œuvre de l'interface dérivée:

type IA = abstract A : int 
type IB = inherit IA 
type IC = inherit IB 

type Baz = 
    interface IC with 
     member x.A = 1 

Donc, dans mon exemple je devrais préciser le type de retour correct explicitement parce que member x.GetEnumerator() dans le type dérivé Bar peut correspondre à la fois IEnumerable.GetEnumerator() et IEnumerable<T>.GetEnumerator().

+1

Just figured out out aussi;) Oui, le problème est que le type de GetEnumerable est ambigu s'il n'est pas spécifié explicitement comme IEnumerable et IEnumerable <'a> spécifier une telle méthode. – Frank

5

Le compilateur ne peut pas déduire le type correct de votre -mise "null". Essayez

open System 

type Foo() = 
    interface Collections.IEnumerable with 
     member x.GetEnumerator() = null 

type Bar() = 
    inherit Foo() 

    interface Collections.Generic.IEnumerable<int> with 
     member x.GetEnumerator() : Collections.Generic.IEnumerator<int> = null 

MISE À JOUR:
La raison en est que le type de la méthode GetEnumerator mis en œuvre par le type Bar est ambigous comme IEnumerable<'a> outils/hérite de la IEnumerable non-générique qui spécifie également un (non générique GetEnumerator méthode. Alors, comment le compilateur devrait-il déduire, quelle méthode exactement vous essayez d'implémenter si tout ce qu'il obtient est nul? Nous avons donc besoin d'une annotation de type dans ce cas.

+0

ok, prenons une interface comme ceci: 'tapez Foo <'a> = résumé M: unité -> 'a' et essayez de l'implémenter sans spécifier aucun type sauf requis dans la déclaration:' type Bar() = interface Foo avec le membre xM() = null' - cela fonctionne parfaitement bien! – ControlFlow

+0

Bien sûr, mais ce n'est pas la même chose. Un exemple équivalent préfèrerait lire 'type Boo <'a> = résumé M: 'a' et' type Foo <'a> = résumé M: unité -> Boo <'a> 'et finalement' type Bar() = interface Foo avec le membre xM() = null '. Encore une fois, le compilateur ne peut pas déduire Boo <_> (comme IEnumerator <_>). – Frank

+0

Hm, tu as raison, mais qu'en est-il du premier exemple? Comment le type correct est déduit là? – ControlFlow