単純なF#引用があるとしましょう:
タイプPet={名前:文字列} exprNonGeneric = <@@ System.Func(fun(x:Pet)-> x.Name)@@>
結果の引用は次のようになります。
val exprNonGeneri:Expr = NewDelegate(System.Func`2 [[FSI_0152 + Pet、FSI-ASSEMBLY、Version = 0.0.0.0、Culture = neutral、PublicKeyToken = null]、[System.String、mscorlib、Version = 4.0.0.0、Culture = neutral、PublicKeyToken = b77a5c561934e089]]、 x、PropertyGet(Some(x)、System.String Name、[]))
ここで一般化したいので、タイプ「Pet」とプロパティ「Name」の代わりに、任意のタイプとメソッド/プロパティを定義して使用できます。これが私がやろうとしていることです:
exprGeneric <'T、' R> f = <@@ System.Func <'T、' R>(%f)@@> exprSpecialized = exprGeneric <Pet、string> <@(fun(x:Pet)-> x.Name)@>
結果の式は次のようになります。
val exprSpecialized:Expr = NewDelegate(System.Func`2 [[FSI_0152 + Pet、FSI-ASSEMBLY、Version = 0.0.0.0、Culture = neutral、PublicKeyToken = null]、[System.String、mscorlib、Version = 4.0.0.0、Culture = neutral、PublicKeyToken = b77a5c561934e089]]、 デリゲート引数、 アプリケーション(ラムダ(x、 PropertyGet(Some(x)、System.String Name、[]))、 デリゲートアーグ))
ご覧のとおり、最初の式と2番目の式の違いは、最初の場合、最上位のNewDelegate式にPropertyGetが含まれ、2番目の式がPropertyGetをApplication/Lambda式でラップすることです。そして、この式を外部コードに渡すと、そのような式の構造を予期せず、失敗します。
したがって、引用の一般化されたバージョンを作成する方法が必要です。したがって、それが特殊化されると、結果の引用は<@@ System.Func(fun(x:Pet)-> x.Name)@@>と完全に一致します。これは可能ですか?または、生成された見積もりにパターンマッチングを手動で適用し、それを必要なものに変換するという選択肢しかありませんか?
更新。回避策として、次のアダプターを実装しました。
convertExpr(expr:Expr)= exprと一致する | NewDelegate(t、darg、appl)-> (darg、appl)と一致する | (delegateArg、appl)-> applと一致する | Application(l、ldarg)-> (l、ldarg)と一致する | (Lambda(x、f)、delegateArg)-> Expr.NewDelegate(t、[x]、f) | _-> expr | _-> expr | _-> expr
それは仕事をします-私は今、式を第1の形式から第2の形式に変換することができます。しかし、式ツリーを横断せずに、これを簡単な方法で実現できるかどうかを調べることに興味があります。