13

私はTomas Petricek と Jon Skeet によるReal-world Functional Programmingという本を読んでいますが、計算式1) (別名モナド) のセクションを理解するのに苦労しています。

この本を通じて、以前の経験とは対照的に、LINQ クエリ式は に限定されずIEnumerable<T>、他のカスタム型でも機能することを学びました。これは私にとって非常に興味深いことであり、クエリ式の構文 ( from x in ... select ...) が適しているシナリオがあるかどうか疑問に思っています。


背景情報:

どうやら、そのようなカスタム型は計算型と呼ばれ、Haskellのモナドと本質的に同じものとして描かれています。私はモナドが何であるかを正確に把握することはできませんでしたが、本によると、それらはbindreturnと呼ばれる 2 つの操作によって定義されます。

関数型プログラミングでは、これら 2 つの操作の型シグネチャは次のようになります (私が思うに):

//    Bind      :    M<A'> -> (A' -> B') -> M<B'>
//
//    Return    :    A' -> M<A'>

Mモナド型の名前です。

C# では、これは次のようになります。

Func< M<A>, Func<A,B>, M<B> >   Bind;

Func< A, M<A> >                 Return;

LINQ Enumerable.Select(射影演算子) は、バインド操作とまったく同じシグネチャを持っていることがわかりM := IEnumerableます。

私のカスタム LINQ 計算タイプ:

この知識を使用して、次のようなカスタム計算タイプを記述できるようになりまし IEnumerable

// my custom computation type:
class Wrapped<A>
{
    // this corresponds to the Return operation:
    public Wrapped(A value)
    {
        this.Value = value;
    }

    public readonly A Value;
}

static class Wrapped
{
    // this corresponds to the Bind operation:
    public static Wrapped<B> Select<A, B>(this Wrapped<A> x, Func<A,B> selector)
    {
        return new Wrapped<B>(selector(x.Value));
    }
}

Wrapped<T>これで、LINQ クエリ式で使用できるようになりました。たとえば、次のようになります。

Wrapped<int> wrapped = new Wrapped<int>(41);

Wrapped<int> answer  = from x in wrapped   // works on int values instead 
                       select x + 1;       // of Wrapped<int> values!

もちろん、この例はあまり役に立ちませんが、クエリ式を作成して、コレクションを操作する以外のことを行う方法を示しています。たとえば、値を何らかの型でラップおよびラップ解除するなどです。


質問:

上記の計算タイプはあまり役に立たないようです。したがって、LINQ クエリ式を利用する (コレクションの処理以外に) 他にどのような合理的な用途があるのでしょうか?


1)セクション 12.4:「代替ワークフローの紹介」、334 ページから。

4

4 に答える 4

4

考え:

  • IEnumerable<T>PushLINQ (私とジョン) - LINQ を (プル モデルではなく) プッシュ モデルに反転します。
  • Reactive Framework / Reactive Extensions - LINQ 構文を組み込んだ別の非常に異なるイベンティング モデル
  • LINQ クエリ構文を使用してスレッド API (ab) を作成しました。私は 100% 納得できなかったので、やめましたが、面白かったです。from( ) などを使用して、列挙型とはまったくSelectMany関係のない分岐/マージ ポイントを選択します
于 2010-06-04T14:01:58.440 に答える
4

私はこれをするのは好きではありませんが (チートのように感じます)、今回は自分自身の質問に答えなければならないと思います。

私はこれについてもう少し考えました。私の質問はややナイーブでした。要するに、LINQ クエリ式 (例: frominwhereselect)foreachは、他のより基本的な構文の上にある構文糖衣であるということです。

  • foreachメソッドを実装するものなら何でも動作しIEnumerator<T> GetEnumerator()ます。IEnumerable<T>たまたまその条件を満たすだけです。

  • from x in xs where x > 0 select -x同様に、LINQ クエリ式は、明確に定義された規則に従って変換されますxs.Where(x => x > 0).Select(x => -x)。一部の型がクエリ演算子メソッドの一部またはすべてを実装している限り、その型はほぼすべての目的で LINQ で使用できます。

私の疑問として残っているのは、コレクションの処理とは別に、LINQ を実際に何に使用できるかということです。LINQクエリ式の構造は非常に厳格であるため、答えは「他にはほとんどない」と思います。常にfrominの部分が必要です。select…も常に必要なようです。結果の式の「言語」が特定の潜在的なシナリオに適合しない場合、他のキーワード ( letorderbygroupbyなど) を使用しても状況は改善されません。LINQ は、データのクエリという 1 つの目標を念頭に置いて非常に明確に設計されており、結果として得られる文法は、おそらく必要以上に LINQ を実際に制限します。

データのクエリ以外の目的での LINQ の可能性と F# 計算式の可能性を比較しましたが、必要なキーワードがそれほど多くないため、より柔軟に見えます。これにより、より多くのシナリオに適したものになる傾向があります。

于 2010-06-10T21:17:36.257 に答える
3

LinqToTwitter では、LINQ を通常とは異なる方法で使用しています。「from」句の中のものは、論理的には列挙可能な型ではありません。ソースを見てください:)

于 2010-06-04T10:46:54.290 に答える