私の質問はこれです:F#タイププロバイダー開発:メソッドを提供するとき、変数番号とタイプのパラメーターにアクセスする方法は?
どのように私は、設計時にこれらの式の数と種類がわからないとき、私は二重引用符にリストから式をスプライスすることができますか?
下段にはタイププロバイダの完全なコードが含まれています。 (私はこの問題を示すために、ダウン概念を取り除いてきました。)私の問題は、これらの行で発生します。ラムダパラメータarg
で
let func = ProvidedMethod((*...*), InvokeCode = fun args ->
<@@ let stringParts =
args
|> List.mapi (fun i arg ->
if paramTypes.[i] = typeof<int> then
sprintf "%i" (%%arg: int)...
、私は次のエラーを取得する:
error FS0446: The variable 'arg' is bound in a quotation but is used as part of a spliced expression. This is not permitted since it may escape its scope.``
私ができます」プロバイダの設計時に値の数や型がわからない場合(パラメータはコンパイル時にはわかりますが)、パラメータ値を「抽出」するようなコードの記述方法を理解してください。
私は、設計時にパラメータの有無や種類を知っていたとき、私はこれを行うことができます。
printfn "%A" (%%args.[0]: int)
しかし、私は内obj list
にExpr list
入力から取得する方法を見つけ出すことはできません引用。ここで
がフルタイププロバイダコードです:最小限の例として
[<TypeProvider>]
type SillyProviderDefinition(config: TypeProviderConfig) as self =
inherit TypeProviderForNamespaces()
let sillyType = ProvidedTypeDefinition(THIS_ASSEMBLY, NAMESPACE, "SillyProvider", Some typeof<obj>)
do sillyType.DefineStaticParameters([ProvidedStaticParameter("argTypes", typeof<string>)], fun typeName args ->
let retType = ProvidedTypeDefinition(typeName, Some typeof<obj>)
let paramTypes =
(args.[0] :?> string).Split([|'|'|])
|> Array.map (function
| "int" -> typeof<int>
| "string" -> typeof<string>
| x -> failwithf "Invalid argType %A. Only string or int permitted" x)
let parameters =
paramTypes
|> Array.mapi (fun i p -> ProvidedParameter(sprintf "arg%i" i, p))
|> Array.toList
let func = ProvidedMethod("Stringify", parameters, typeof<string>, IsStaticMethod = true, InvokeCode = fun args ->
<@@ let stringParts =
args
|> List.mapi (fun i arg ->
if paramTypes.[i] = typeof<int> then
sprintf "%i" (%%arg: int)
elif paramTypes.[i] = typeof<string> then
(%%arg: string)
else
failwith "Unexpected arg type")
//printfn "%A" (%%args.[0]: int)
String.Join("", stringParts) @@>)
do retType.AddMember func
do sillyType.AddMember retType
retType)
do self.AddNamespace(NAMESPACE, [sillyType])
あなたは、そのコードが型プロバイダクラスのコンテキストでどこに行くのか教えていただけますか?コンパイル単位 'TypeProviderPain'からのモジュール/名前空間 'StartupCode $ TypeProviderPain>。$ Library1'は実行されませんでしたが、実行しようとしたときに次のエラーが発生しました。モジュール名または型が含まれています 'formatInt @ 47''' '' scripty.fsx(7,9):エラーFS1109:アセンブリの'。$ [email protected] '型への参照'TypeProviderPain'が見つかりましたが、タイプはアセンブリ内に見つかりませんでした。 ' –
"formatInt"と "formatString"を独自のモジュールに移動することで、このランタイムエラーを解消できました。同様のエラーを避けるために、 "String.concat"を "String.Join"に置き換える必要もありました: '' error FS0193:コンパイルユニット 'FSharp.Core'のモジュール/名前空間 'Microsoft.FSharp.Collections'に名前空間、モジュールまたは型 'StringModule'''。これらの手順を実行した後、私は**型プロバイダを実行することができました。 –
この種のエラーは、悲しいことに通常のタイプのプロバイダーの痛みです...うまくいけばうまくいきます! –