这是一个F#错误吗?

时间:2010-10-04 14:25:26

标签: f# interface ienumerable

我有一个实现IEnumerable<T>接口的类型,一切正常:

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.
*/

2 个答案:

答案 0 :(得分:5)

编译器无法从“null”实现中推断出正确的类型。尝试

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

更新:
原因是GetEnumerator类型实现的Bar方法的类型是不明确的,因为IEnumerable<'a>实现/继承了非泛型IEnumerable,它也指定了一个(非) -generic)GetEnumerator方法。那么,编译器应该如何推断出,如果他获得的所有方法都是null,那么您正在尝试实现哪种方法?因此,在这种情况下我们需要一个类型注释。

答案 1 :(得分: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()都匹配。