4
type Interpreter<'a> =
| RegularInterpreter of (int -> 'a)
| StringInterpreter of (string -> 'a)

let add<'a> (x: 'a) (y: 'a) (in_: Interpreter<'a>): 'a = 
    match in_ with
    | RegularInterpreter r -> 
        x+y |> r
    | StringInterpreter r -> 
        sprintf "(%s + %s)" x y |> r

'aコンパイル時に解決できないというエラーメッセージは、私には明らかです。上記の作業を行うことが可能かどうかという質問に対する答えは、関数をデータ型に直接追加することを除けば、いいえであると推測しています。しかし、インターフェイスを使用したり、ジェネリック パラメーターを完全に削除したりすることもできます。

編集:マークの返信は実際に私が尋ねたことを行いますが、適切に説明しなかったので質問を拡張させてください. 私がやろうとしているのは、上記の手法を使用して、この投稿で行われたことを模倣することです。これの動機は、インライン化された関数は構成可能性が低いため、回避することです。一般的な引数を特殊化せずにラムダとして渡すことはできません。

ジェネリック引数を持つユニオン型をクロージャーに渡すことで回避できるかもしれないと思っていましたが...

type Interpreter<'a> =
| RegularInterpreter of (int -> 'a)
| StringInterpreter of (string -> 'a)

let val_ x in_ =
    match in_ with
    | RegularInterpreter r -> r x
    | StringInterpreter r -> r (string x)

let inline add x y in_ = 
    match in_ with
    | RegularInterpreter r -> 
        x in_ + y in_ |> r
    | StringInterpreter r -> 
        sprintf "(%A + %A)" (x in_) (y in_) |> r

let inline mult x y in_ = 
    match in_ with
    | RegularInterpreter r -> 
        x in_ * y in_ |> r
    | StringInterpreter r -> 
        sprintf "(%A * %A)" (x in_) (y in_) |> r

let inline r2 in_ = add (val_ 1) (val_ 3) in_

r2 (RegularInterpreter id)
r2 (StringInterpreter id) // Type error.

この最後の行で型エラーが発生します。これを回避する方法はありますか?ただし、構成可能性に制限があるため、関数をインライン化しないことをお勧めします。

4

4 に答える 4

4

型注釈を削除します。

let inline add x y in_ = 
    match in_ with
    | RegularInterpreter r -> 
        x + y |> r
    | StringInterpreter r -> 
        sprintf "(%A + %A)" x y |> r

他にもいくつかの変更を加える必要がありますが、これも上で組み込みました。

  • で使用される書式指定子sprintfをより一般的なものに変更します。を使用する場合%s、そのプレースホルダーの引数は文字列でなければならないので、コンパイラはxystring値であると推測します。
  • inlineキーワードを追加します。

これらの変更により、 の推定型addは次のようになりました。

x: ^a -> y: ^b -> in_:Interpreter<'c> -> 'c
    when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b -> int)

+が入力引数を に変換すると定義されている任意の型で機能することがわかりますint。実際にはint、カスタム オペレータを定義しない限り、それはおそらくそれ自体のみを意味します。

FSI スモークテスト:

> add 3 2 (RegularInterpreter id);;
val it : int = 5
> add 2 3 (StringInterpreter (fun _ -> 42));;
val it : int = 42
于 2016-12-25T16:29:11.107 に答える