2

非同期 HTTP API クライアント モジュール/ライブラリを作成しています。すべてを可能な限り DRY にするために、API 呼び出しを行う個別の部分からすべての HTTP API 呼び出しを構成しようとしています。ボトムアップ: 要求の構築、応答の取得、応答の文字列バッファーへの読み取り、JSON コンテンツの解析その文字列バッファをオブジェクトに。

これまでのところ、私はこのコードを持っています:

module ApiUtils =
    // ... request builder fns omitted ...

    let getResponse<'a> (request : Net.WebRequest) = 
        request.AsyncGetResponse()

    let readResponse (response : Net.WebResponse) =
        use reader = new StreamReader(response.GetResponseStream())
        reader.AsyncReadToEnd()

    let getString = getResponse >> (Async.flatMap readResponse)

    let parseJson<'T> responseText : 'T =
        Json.JsonConvert.DeserializeObject<'T> responseText

    let getJson<'T> = getString >> (Async.map parseJson<'T>)

そして、ご覧のとおり、私は独自の追加で Async モジュールを拡張しました。

module Async =
    let map f m =
        async {
            let! v = m
            return f v
        }

    let flatMap f m =
        async {
            let! v = m
            return! f v
        }

私が達成しようとしている目標はasync、計算式の構文を最大限に活用するために、ブロックで使用できる関数を含むモジュールを構築することです。私はそれを正しく行っているかどうか、正しい名前を選択しているかどうかなどを疑問に思っていました.正式な関数型プログラミングの教育はほとんどまたはまったく受けていません。

4

1 に答える 1

6

F# で非同期コードを記述する場合、より高度なコンビネーターを構築するよりも、組み込みの計算非同期ワークフロー構文を使用する方が簡単だと思います。

あなたの例では、簡単な関数を書くだけならコードを実際に複製することはないので、以下はDRYの原則を破ることはなく、かなり単純だと思います(また、コードを拡張して例外を処理するのも簡単です。そうでなければ難しいでしょう):

let getJson<'T> (request:Net.WebRequest) = async { 
  let! response = request.AsyncGetResponse()
  use reader = new StreamReader(response.GetResponseStream())
  let! data = reader.AsyncReadToEnd()
  return Json.JsonConvert.DeserializeObject<'T> data }

もちろん、他の目的でコードの別の場所にデータをダウンロードする必要がある場合は、コードをdownloadDataとに分割できます。getJson

一般に、機能コードを作成する場合、計算を構成する方法として 2 つのオプションがあります。

  • 言語構文の使用 (単純な F# と非同期ワークフローの両方でのループ、letおよびなど)。言語は計算を記述するように設計されており、それをうまく実行できるため、このアプローチは通常、計算を記述する場合にうまく機能します。try .. withuse

  • カスタム コンビネータ ( map>>|>またはライブラリ固有の演算子など) の使用。これは、対話型アニメーション、ストック オプション、ユーザー インターフェイス コンポーネント、パーサーなど、単なる計算ではないものをモデル化する場合に必要です。ただし、言語の基本的な機能が問題を表現するのに十分でない場合にのみ、この道をたどります。

それはさておき、HTTP リクエストJSON 解析JSON タイプ プロバイダーなどのさまざまなタスクのヘルパーを実装するF# データ ライブラリに興味があるかもしれません。

于 2013-01-21T15:17:04.947 に答える