Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ query expressions that operate on types (monads?) other than IEnumerable<T> -- Possible uses?

I'm reading the book Real-world functional programming by Tomas Petricek and Jon Skeet and I'm having a hard time digesting the section on computation expressions1) (aka monads).

Through this book, I learnt that — contrary to my previous experiences — LINQ query expressions aren't restricted to IEnumerable<T>, but can work on other custom types as well. This seems very interesting to me, and I am wondering if there are scenarios where the query expression syntax (from x in ... select ...) would be a nice fit.


Some background info:

Apparently, such custom types are called computation types, which are portrayed as being essentially the same thing as monads in Haskell. I have never been able to grasp what exactly monads are, but according to the book, they are defined through two operations called bind and return.

In functional programming, the type signatures of these two operations would be (I think):

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

where M is the monadic type's name.

In C#, this corresponds to:

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

Func< A, M<A> >                 Return;

It turns out that LINQ's Enumerable.Select (the projection operator) has exactly the same signature as the bind operation with M := IEnumerable.

My custom LINQ computation type:

Using this knowledge, I can now write a custom computation type which is not 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));
    }
}

And now I can use Wrapped<T> in LINQ query expressions, e.g.:

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!

Of course this example is not very useful, but it demonstrates how query expressions can be made to do something else than working with collections, e.g. wrapping and unwrapping values with some type.


Question:

The above computation type doesn't seem very useful. Therefore I wonder, what other reasonable uses (besides processing collections) could there be that make use of LINQ query expressions?


1) Section 12.4: "Introducing alternative workflows", starting on page 334.

like image 657
stakx - no longer contributing Avatar asked Jun 04 '10 10:06

stakx - no longer contributing


People also ask

What are LINQ query expressions?

Language-Integrated Query (LINQ) is the name for a set of technologies based on the integration of query capabilities directly into the C# language. Traditionally, queries against data are expressed as simple strings without type checking at compile time or IntelliSense support.

What is the use of any in LINQ?

The Any operator is used to check whether any element in the sequence or collection satisfy the given condition. If one or more element satisfies the given condition, then it will return true. If any element does not satisfy the given condition, then it will return false.

Is LINQ a Monad?

LINQ is monad. It is very carefully designed by Erik Meijer so that it is monad.

What are query expressions?

A query expression defines the search criteria for retrieving documents using ConText. A query expression consists of query terms (words and phrases) and other components such as operators and special characters which allow users to specify exactly which documents are retrieved by ConText.


1 Answers

Thoughts:

  • PushLINQ (me and Jon) - reverses LINQ to a push model (rather than the IEnumerable<T> pull model)
  • Reactive Framework / Reactive Extensions - another very different eventing model incorporating LINQ syntax
  • I wrote a threading API (ab)using the LINQ query syntax; I wasn't 100% convinced by it, so ditched it - but it was interesting; used from (SelectMany) etc to pick out branch/merge points completely unrelated to enumerables
like image 72
Marc Gravell Avatar answered Oct 09 '22 11:10

Marc Gravell