2010-04-30 9 views
9

En F #, dada la clase siguiente:F de error # compilación: aplicación de un tipo inesperado

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

¿Por qué la siguiente compilación:

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

Mientras que el siguiente no se compile:

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

No estoy seguro, pero la eliminación de la de la llamada a Bar resultados en ningún error. –

+0

Es cierto, pero eso efectivamente hace que use System.Object internamente. Si tuviera que usar typeof <'t> como parte de alguna prueba, sería un poco inútil. –

Respuesta

14

Parece que no se admite el suministro de parámetros de tipo al tratar el método como un valor de primera clase. Comprobé el F# specification y aquí están algunas partes importantes:

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.

Si especifica argumentos de tipo y argumentos, a continuación, aplica el primer caso, pero como se puede ver, la especificación requiere algunos argumentos reales también. Aunque no estoy seguro de cuál es la motivación detrás de esto.

De todos modos, si se utiliza el parámetro de tipo en cualquier lugar de la firma del miembro de tipo, entonces se puede especificar que el uso de anotaciones de tipo así:

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

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

Por otro lado, si usted no usa el parámetro de tipo en cualquier lugar de la firma, entonces no estoy muy seguro de por qué lo necesita en primer lugar. Si lo necesita sólo para algún tipo de procesamiento en tiempo de ejecución, entonces usted puede ser capaz de tomar la representación de tipo en tiempo de ejecución como un argumento:

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

let f = new Foo() 
"string" |> f.Bar typeof<Int32> 
Cuestiones relacionadas