Ошибка компиляции F#: приложение неожиданного типа

В F# для следующего класса:

type Foo() =
    member this.Bar<'t> (arg0:string) = ignore()

Почему компилируется следующее:

let f = new Foo()
f.Bar<Int32> "string"

Пока следующее не будет компилироваться:

let f = new Foo()
"string" |> f.Bar<Int32> //The compiler returns the error: "Unexpected type application"

person Jim Burger    schedule 30.04.2010    source источник
comment
Не уверен, но удаление ‹Int32› из вызова Bar не приводит к ошибке.   -  person OJ.    schedule 30.04.2010
comment
Верно, но это фактически заставляет его использовать System.Object внутри. Если бы вы использовали typeof‹'t› как часть какого-то теста, это было бы немного бесполезно.   -  person Jim Burger    schedule 30.04.2010


Ответы (1)


Похоже, что предоставление параметров типа при обработке метода как значения первого класса не поддерживается. Я проверил спецификацию F# и вот некоторые важные биты:

14.2.2 Поиск по элементам
[Если выражение приложения начинается с:]

  • <types> expr, затем используйте <types> в качестве аргументов типа и expr в качестве аргумента выражения.
  • выражение, затем используйте выражение в качестве аргумента выражения.
  • в противном случае не используйте аргумент выражения или аргумент типа.
  • Если [метод] помечен атрибутом RequiresExplicitTypeArguments, то должны быть заданы явные аргументы типа.

Если вы указываете аргументы и аргументы типа, то применяется первый случай, но, как видите, спецификация также требует некоторых фактических аргументов. Я не совсем уверен, что мотивация стоит за этим, хотя.

В любом случае, если вы используете параметр типа где-либо в сигнатуре типа члена, вы можете указать его с помощью аннотаций типа, подобных этой:

type Foo() = 
  member this.Bar<´T> (arg0:string) : ´T = 
    Unchecked.defaultof<´T>

let f = new Foo()
"string" |> (f.Bar : _ -> Int32)

С другой стороны, если вы нигде в подписи не используете параметр типа, то я не совсем понимаю, зачем он вообще вам нужен. Если вам это нужно только для некоторой обработки во время выполнения, вы можете использовать представление типа во время выполнения в качестве аргумента:

type Foo() = 
  member this.Bar (t:Type) (arg0:string) = ()

let f = new Foo() 
"string" |> f.Bar typeof<Int32>
person Tomas Petricek    schedule 30.04.2010