2010-04-30 5 views
9

В 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" 
+0

Не уверен, но удаляя от вызова Bar результатов без ошибок. –

+0

Правда, но это эффективно заставляет System.Object внутренне. Если бы вы использовали тип <'t> как часть некоторого теста, это было бы немного бесполезно. –

ответ

14

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

14.2.2 Item-Qualified Lookup
[If the application expression begins with:]

  • <types> expr, then use <types> as the type arguments and expr as the expression argument.
  • expr, then use expr as the expression argument.
  • otherwise use no expression argument or type arguments.
  • If the [method] is labelled with the RequiresExplicitTypeArguments attribute then explicit type arguments must have been given.

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

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

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>