1


0

型の関数(ユニット→ユニット)でF#の静的に解決された型パラメーターを使用できますか?

なぜこれが許可されないのですか?

type Foo() =
    static member Bar() = ()

let inline bar<^a>() = //ERROR: unexpected infix operator in pattern
    (^a : (static member Bar : unit -> unit)())

//Hypothetical usage: let _ = bar()

…​but this works fine?

type Foo() =
    static member Bar() = new Foo()

let inline bar() : ^a =
    (^a : (static member Bar : unit -> ^a)())

let x : Foo = bar()

静的に解決された型パラメーターを持つ関数は、解決された型のインスタンスを返すために必要ですか?

2 Answer


6


お気づきのように、F#は文字シーケンス `<^`を中置演算子として扱うため、スペースで区切る必要があります。 制約を明示的に指定する必要がある場合の質問に関しては、関数型パラメーターを明示的に指定するときに必要な制約も指定する必要があるというルールがあると思います。 それ以外の場合、F#が型パラメーターと制約を推測できる場合、それらを指定する必要はありません。

したがって、あなたの質問のこの例はうまくいきます:

let inline bar() :^a =
  (^a : (static member Bar : unit -> ^a)())

これのように:

let inline bar(x : ^a) =
  (^a : (static member Bar : unit -> unit)())

ジェネリック型パラメーターがありますが、関数に明示的に配置していないため、F#は必要な制約を推測できます。

一方、明示的なジェネリックパラメーターを省略するために他の例を変更しようとすると、次のようになります。

let inline bar() =
  (^a : (static member Bar : unit -> unit)())

F#はこれを許可しないことがわかります。これは、 `bar()`の呼び出しに対して `^ a`をインスタンス化する方法を把握する方法がないためです。 したがって、typeパラメーターを明示的に指定する必要があります。指定すると、制約も明示的に指定する必要があります。


1


理解した。 山括弧内のスペースと制約が必要です。

これは動作します:

type Foo() =
    static member Bar() = ()

let inline bar< ^a when ^a : (static member Bar : unit -> unit) >() =
    (^a : (static member Bar : unit -> unit)())

let _ = bar()

このことから、関数が静的に解決された型のインスタンスを返す場合、制約はオプションであると推測できます。 それがルールかどうかは誰にもわかりますか?