4

を使用していFSharp.Data typeprovidersます。

typeprovider'sサンプル文字列またはファイルの場所を設定するパラメーターを持つ関数を作成したいと思います。

let SyncIt url sample converter storer =
    async {
        url
        |> MakeRequestAsync 
        |> Async.RunSynchronously
        |> JsonProvider< sample >.Parse
        |> Seq.iter (converter >> storer)
    }

モジュール内の JsonProvider を呼び出す場合

[<Literal>]
let sample = """{"name":"Peter","age":9}"""

type provider = JsonProvider<sample>

正常に動作します。として渡すことができないのはなぜparameterですか? コンパイル時に参照が明確になることに関係があることは知っていますが、それぞれを宣言する以外にそれを回避する方法がわかりませんproviders explicitly

4

1 に答える 1

8

値はコンパイル時に決定される必要があるため、関数は引数として静的パラメーターの値を取ることはできません。これは、次のように書くと次​​のことを意味します。

let [<Literal>] sample = """{"name":"Peter","age":9}"""
let parseHtml html = JsonProvider<sample>.Parse(html)

...コンパイラはそれsampleが定数であることを認識しているため(およびコンパイラはその値を認識しているため)、(コンパイル中に)型プロバイダーをインスタンス化して型を生成できるため、すべて問題ありません。次のようなものを書く場合:

let parseHtml sample html = JsonProvider<sample>.Parse(html)

...その後、コンパイラはsample実行時に の値が何であるかを知ることができないため、コンパイル時に必要な型を生成できません。型プロバイダーは実行時に「存在」しないため、その場で型を生成することはできません (型プロバイダーのポイントは、コンパイル時の安全性の保証を提供することであるため、これはあまり役に立ちません)。

あなたの例。JsonProvider<sample>.Parseあなたの場合、代わりに特定の関数を引数として取るのが理にかなっているかもしれません:

let SyncIt url parse storer =
    async {
        url
        |> MakeRequestAsync 
        |> Async.RunSynchronously
        |> parse
        |> Seq.iter (converter >> storer)
    }

このようにして、呼び出し元は静的パラメーターを型プロバイダーに指定し、関数を呼び出して同期を行うことができます。

let [<Literal>] sample = """{"name":"Peter","age":9}"""
SyncIt url (JsonProvider<sample>.Parse) storer

ただし、ここで型プロバイダーが必要な理由は完全にはわかりません。プロバイダーのポイントは、データの具体的なソースにアクセスするために使用できるナイス タイプを提供することです。converterJSON データ ファイルでstorer作業している場合は、 JSON パーサー (F# データでも)だけを使用して作業を完了できる可能性があります。

非同期ブロック。また、コードは実際には非同期で実行されていないことに注意してください。非同期にするには、let!操作を使用して URL をダウンロードする必要があります。

let SyncIt url parser storer =
    async {
        let wc = new WebClient() 
        let! html = wc.AsyncDownloadString(url)
        parser html
        |> Seq.iter (converter >> storer)
    }
于 2013-06-03T13:40:15.463 に答える