2010-10-04 93 views
2

我有一個正在實施IEnumerable<T>接口的類型,一切正常:這是一個F#bug嗎?

open System 

type Bar() = 

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

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

但如果類型繼承通過基本類型IEnumerable接口實現的東西出了問題:上面

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 

代碼生成型推理錯誤:

  • 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>'.

我做得不對或這是F#編譯器錯誤?

Microsoft (R) F# 2.0 Interactive build 4.0.30319.1


更新更典型的例子:

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

你能發佈你的實際代碼嗎? – Gabe 2010-10-04 14:38:35

回答

2

這是不是一個錯誤,這只是一個類型推斷失敗,因爲F#中派生的接口實現聲明可以實現繼承接口成員:

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

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

所以在我的例子中,我應該指定正確的返回類型明確地因爲member x.GetEnumerator()派生的Bar類型可能匹配IEnumerable.GetEnumerator()IEnumerable<T>.GetEnumerator()

+1

);是的,問題在於如果沒有明確指定GetEnumerable的類型,那麼IEnumerable和IEnumerable都會指定這樣一種方法。 – Frank 2010-10-05 12:32:58

5

編譯器不能推斷出從 「空」 - 實施正確的類型。嘗試

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 

更新:
其原因是,由Bar類型實現的GetEnumerator方法的類型是ambigous作爲IEnumerable<'a>工具/繼承了非通用IEnumerable其還指定(非通用)GetEnumerator方法。那麼,編譯器應該如何推斷,如果他得到的所有內容都是null,那麼您正在試圖實現哪種方法?因此,在這種情況下我們需要一個類型註釋。

+0

好吧,讓我們看看如下的接口:'type Foo <'a> = abstract M:unit - >'a'並嘗試去實現它,但沒有指定任何類型,除了聲明中需要的:'type Bar()= interface Foo with member xM ()= null' - 它工作得非常好! – ControlFlow 2010-10-04 14:46:51

+0

當然,但這不一樣。一個等價的樣本寧願閱讀'type Boo <'a> = abstract M:'a'和'type Foo <'a> = abstract M:unit - > Boo <'a>'最後'type Bar()= interface Foo with member xM()= null '。再次,編譯器不能推斷Boo <_>(如IEnumerator <_>)。 – Frank 2010-10-04 14:56:10

+0

嗯,你說得對,但第一個例子呢?如何在那裏推斷正確的類型? – ControlFlow 2010-10-04 15:08:54