Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cross Type LINQ

Tags:

.net

linq

I have the following code

    [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;

    }

My Maybe type accepts all the Select and SelectMany methods to make it Linq compatible and I have tests to prove it so. However I can't seem to figure out a way to do cross type LINQ composition as in the above test case. The error I get is

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*

Is there a way to combine the two LINQ types or am I out of luck here? The complete Maybe.cs implementation is at

https://gist.github.com/4016243

like image 345
bradgonesurfing Avatar asked Mar 07 '26 15:03

bradgonesurfing


2 Answers

The translation of this:

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

is simply:

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

Note that nothing is being called on y here.

Now l is a List<Maybe<int>>, so you need to try to find an appropriate SelectMany method which would be valid here. Unless you've added any more, it will look in Enumerable.SelectMany, and every overload there requires the the first delegate to return an IEnumerable<T> for some T.

So that's why it's not working. You could make it work by making Maybe<T> implement IEnumerable<T> (presumably either yielding a single result or no results). It's hard to say for sure whether that's what you're aiming for, but you've basically got to get that expansion to work.

Alternatively, you could write a new overload for SelectMany targeting IEnumerable<T>, for cases where the result is a Maybe<T> rather than an IEnumerable<T>. That would be pretty unintuitive though, IMO.

like image 177
Jon Skeet Avatar answered Mar 09 '26 05:03

Jon Skeet


Your SelectMany method takes a Maybe<TSource> as a parameter, but you're using it on a List<Maybe<TSource>>, so it actually uses the SelectMany method from Enumerable. It's not clear from your example what you expect the type of y to be, but as it is the code doesn't really make sense.

like image 26
Thomas Levesque Avatar answered Mar 09 '26 04:03

Thomas Levesque



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!