В 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"
Похоже, что предоставление параметров типа при обработке метода как значения первого класса не поддерживается. Я проверил спецификацию F # и вот несколько важных моментов:
14.2.2 Поиск с определением элемента
[Если выражение приложения начинается с:]
expr , затем используйте
в качестве аргументов типа и
expr
в качестве аргумента выражения .- expr , затем используйте 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>