2015-10-02 10 views
7

は、私は2つの異なるライブラリ種類を持って考えてみましょう。 FooBarはライブラリコードの一部であるため、変更できません。 hereが説明したようにインライン関数と型エクステンション

はここで型拡張やインライン関数を使用して私の最初の試みです:

// Library.fs 
module Library 

type Foo = { foo : string } 
type Bar = { bar : int32 } 

// Program.fs 
type Foo with 
    static member zoo (f : Foo) = "foo" 

type Bar with 
    static member zoo (b : Bar) = "bar" 

let inline zoo (x : ^t) = 
    (^t : (static member zoo : ^t -> string) x) 

let f = zoo { foo = "1" } // error FS0001: The type 'Foo' does not support the operator 'zoo' 

インライン関数の定義は、タイプの拡張子に依存していないのはなぜ? FooBarタイプの定義を変更せずに問題を解決するにはどうすればよいですか?

答えて

11

メソッドのオーバーロードを使用します。

拡張メソッドの問題は、solving member constraintsの場合には考慮されないということです。

あなた自身の答えにすでに示されているように、メソッドのオーバーロードを使用することができます。さらに、中間型と中間メソッド(この場合は演算子を簡単にする)を使用してインライン汎用関数を作成し、トリック:

type T = T with 
    static member ($) (T, x:Foo) = "foo" 
    static member ($) (T, x:Bar) = "bar" 

let inline zoo x = T $ x 

let f = zoo { foo = "1" } 

ここでは、この動作についてはmore detailsです。

この関数はインライン化されるので、たとえばC#から呼び出すことができないことに注意してください。関数を使用しない場合は、単純で標準的なメソッドオーバーロードを使用してください。

1

私がこれまで得ることができる最善のことは、それが最善ではなく、非常に汎用的なソリューションではありませんが、少なくともそれが動作

type Ext = 
    static member zoo (f : Foo) = "foo" 
    static member zoo (b : Bar) = "bar" 

let f = Ext.zoo { foo = "1" } // "foo" 
let b = Ext.zoo { bar = 2 } // "bar" 

です。

関連する問題