3

次のコードがあります

    [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]
    public void TestEnumOfMaybe()
    {
        List<Maybe<int>> l = new List<Maybe<int>>();
        l.Add(1.ToMaybe());
        l.Add(Maybe.None<int>());
        l.Add(3.ToMaybe());

        var y = from x in l
                from y in x
                select y;

    }

私の Maybe 型は、すべての Select および SelectMany メソッドを受け入れて Linq と互換性があり、それを証明するテストがあります。ただし、上記のテスト ケースのように、クロス タイプの LINQ コンポジションを行う方法がわかりません。私が得るエラーは

expression of type 'FunctionalExtensions.Maybe<int>' is not allowed in
a subsequent from clause in a query expression with source type
'System.Collections.Generic.List<FunctionalExtensions.Maybe<int>>'.  

Type inference failed in the call to 'SelectMany'.
FunctionalExtensions*

2 つの LINQ 型を組み合わせる方法はありますか、それとも運が悪いのでしょうか? 完全な Maybe.cs の実装は次の場所にあります。

https://gist.github.com/4016243

4

4 に答える 4

6

これの翻訳:

// Changed variable from y to query for clarity
var query = from x in l
            from y in x
            select y;

単純です:

var query = l.SelectMany(x => x, (x, y) => y);

ここではも呼び出されていないことに注意してyください。

現在lは であるため、ここで有効List<Maybe<int>>な適切なメソッドを見つける必要があります。SelectManyこれ以上追加しない限り、 が検索されEnumerable.SelectMany、そこにあるすべてのオーバーロードでは、最初のデリゲートがIEnumerable<T>for someを返す必要がありTます。

それが機能していない理由です。Maybe<T>実装することで機能させることができますIEnumerable<T>(おそらく、単一の結果が得られるか、結果が得られません)。それがあなたが目指しているものかどうかを確実に言うのは難しいですが、基本的にはその拡張を機能させる必要があります。

または、SelectMany結果IEnumerable<T>が. ただし、それはかなり直感的ではありません。Maybe<T>IEnumerable<T>

于 2012-11-05T09:27:36.813 に答える
1

メソッドSelectManyMaybe<TSource>パラメータとして を受け取りますが、 で使用しているList<Maybe<TSource>>ため、実際には のSelectManyメソッドを使用しEnumerableます。あなたの例からは、タイプが何になると予想されるかは明確yではありませんが、コードは実際には意味がありません。

于 2012-11-05T09:29:19.470 に答える
0

私の特定の問題については、おそらくIEnumerableを実装することが道であり、IOBservableのサポートも簡単であることがわかりました。現在合格している私の2つのテストケース。

    [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]
    public void TestEnumOfMaybe()
    {
        List<Maybe<int>> l = new List<Maybe<int>>();
        l.Add(1.ToMaybe());
        l.Add(Maybe.None<int>());
        l.Add(3.ToMaybe());

        var k = from q in l
                from y in q
                select y;

        k.Should().BeEquivalentTo(new[] { 1, 3 });

    }

    [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]
    public void TestObservableOfMaybe()
    {
        List<Maybe<int>> l = new List<Maybe<int>>();
        l.Add(1.ToMaybe());
        l.Add(Maybe.None<int>());
        l.Add(3.ToMaybe());

        var o = l.ToObservable();

        var k = from q in o
                from y in q
                select y;

        var m = k.ToEnumerable();

        m.Should().BeEquivalentTo(new[] { 1, 3 });

    }

一般に、SelectMany シグネチャが並んでいても、LINQ システムは異なる型を一緒にチェーンすることを禁止していると思います。そうでなければ、私はまだ確信していません。

于 2012-11-05T12:21:51.583 に答える
0

fromJon が指摘しているように、 , fromtoの LINQ 翻訳SelectManyは次のとおりです。

var query = l.SelectMany(x => x, (x, y) => y);

最初に注意すべきことは、 yourSelectManyが individual に対して定義されていることMaybe<T>です。したがって、これが意味をなすためには、リストではなく(一部の) でlある必要があります。次に注意すべきことは、署名が一致する必要があることです。例えば:Maybe<T>T

public static Maybe<TResult> SelectMany<TSource, TMaybe, TResult>(
    this Maybe<TSource> m, Func<Maybe<TSource>, Maybe<TMaybe>> f,
    Func<Maybe<TSource>, Maybe<TMaybe>, TResult> g)
{
    throw new NotImplementedException();
    // return m.Bind(x => f(x).Bind(y => g(x, y).ToMaybe()));
}

と:

var obj = l[0];

これが機能するようになりました(明示的なジェネリック):

var q = obj.SelectMany<int, int, Maybe<int>>((x => x), (x, y) => y);

これは次と同じです:

var r = obj.SelectMany((x => x), (x, y) => y);

これは次と同じです:

var query = from x in obj
            from y in x
            select y;
于 2012-11-05T09:59:51.513 に答える