Это ошибка F #? - PullRequest
       33

Это ошибка F #?

2 голосов
/ 04 октября 2010

У меня есть тип, который реализует интерфейс 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 ]

5 голосов
/ 04 октября 2010

Компилятор не может определить правильный тип из вашей "нулевой" реализации.Попробуйте

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, который также определяет (неуниверсальный) метод GetEnumerator.Итак, как должен выводить компилятор, какой именно метод вы пытаетесь реализовать, если все, что он получает, является нулем?Поэтому нам нужна аннотация типа в этом случае.

2 голосов
/ 05 октября 2010

Это не ошибка, это просто ошибка вывода типа, потому что 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().

...