let inline と member 制約を使用すると、既知のメンバーに対してダック タイピングを行うことができますが、次のようなジェネリック関数を定義したい場合はどうでしょうか。
let ダックラッパー<'a> アヒル = ...
署名 'b -> 'a を使用し、戻り値は 'a (インターフェース) を実装し、duck への呼び出しを転送するオブジェクトになります。
Reflection.Emit を使用して C# でこれを実行しましたが、F# のリフレクション、引用符、またはその他の構成要素を使用すると簡単になるかどうか疑問に思っています。
これを達成する方法について何か提案はありますか?
Timsの回答を読んだ後に編集 して、もう少し詳細を説明したいと思いました
引用を使って助けることについて書いたとき、私が考えていたのは次のようなものでした:
{new IInterface with member x.SayHello() = !!<@ %expr @>}
!! 引用符を関数に変換する演算子であり、 %expr はメソッドの作業単位です。式を関数に変換することはできますが(推測します)、方法がわかりません
IInterface は 'a になるので、もちろん、これでうまくいくわけではありません。F# リフレクションが便利な関数を持ち、型オブジェクトといくつかの関数値に基づいて型を構築できることを願っています。
EDIT Tomas Petricekの回答の更新として、私のニーズを説明するコードをいくつか提供します
type SourceRole =
abstract transfer : decimal -> context
and context(sourceAccount:account, destinationAccount) =
let source = sourceAccount
let destination = destinationAccount
member self.transfer amount =
let sourcePlayer =
{new SourceRole with
member this.transfer amount =
use scope = new TransactionScope()
let source = source.decreaseBalance amount
let destination = destination.increaseBalance amount
scope.Complete()
context(source,destination)
}
sourcePlayer.transfer(amount)
これは、 DCIの教科書の例をF# に移植する試みです。ソースと宛先は DCI ロールです。特定のコントラクトに準拠するデータ オブジェクトは、それらを再生できるという考えです。この場合、契約は簡単です。source には reduceBalance というメンバー関数が必要であり、destination には increaseBalance というメンバー関数が必要です。この特定のケースでは、let inline とメンバーの制約を使用してそれを実現できます。しかし、インターフェイスとオブジェクトを指定した一連の関数を書きたいと思います。この場合、それはソース (オブジェクトとして) であり、
type sourceContract =
abstract decreaseBalance : decimal -> sourceContract
タイプとして。結果は、ソース オブジェクトの同じ名前のメソッドにメソッド呼び出しをパイプする sourceContract 型のオブジェクトになります。