Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm looking into LINQ and the query language appears (at least on the surface) to be nothing more than an implementation of map and/or list comprehensions as found in Haskell and other FP languages (particularly the generalisation of 'map' and 'for' in Scala). Is this correct? Is there more to the syntax than this? From the breathless tone of the book I'm reading ("Essential LINQ") it would seem like there's something new or innovative here.

There's the whole back-end, pipeline, first-order expression trees and types etc to implement LINQ but my question is about the query language itself.

Cheers

Joe

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
110 views
Welcome To Ask or Share your Answers For Others

1 Answer

Functionally spoken, LINQ is nothing but a syntactic simplification of expressing monads. Linq to Objects (List-comprehensions - even this would already be extremely useful), which you have been talking about, is just one possible application of this (similar to the List-Monad in Haskell).

If you write

from x in expr1
from y in expr2
select x + y

it's nothing but

do
    x <- expr1
    y <- expr2
    return $ x + y

in Haskell.

The concrete thing that is done depends on user-defined Linq-providers (Extension-Methods) of which Linq.Enumerable is just one implementation involving IEnumerables.

By providing one, you can create completely new LINQ-semantics for your types.

Example: Given an Option type for computations that may fail (nullable values), one could define a Linq-provider for querying over them.

public static class MaybeExtensions
{
public static Option<T> ToMaybe<T>(this T value)
{
    return Option<T>.Some(value);
}

public static Option<U> SelectMany<T, U>(
    this Option<T> m, 
    Func<T, Option<U>> k)
{
    return !m.IsNone ? Option<U>.None : k(m.Value);
}

public static Option<V> SelectMany<T, U, V>(
    this Option<T> m, 
    Func<T, Option<U>> k, 
    Func<T, U, V> s)
{
    return m.SelectMany(x => k(x).SelectMany(y => s(x, y).ToMaybe()));
}
} 

This would now allow us to write such code:

var sum = from x in ReadNumber("x")
          from y in ReadNumber("y")
          select x + y; 

The computation will only return a value if all computations succeeded and will otherwise fail at the first failing one.

In combination with expression trees, Linq can be extremely powerful and allows you to express -

  1. Database accesses
  2. Asynchronous programm flow
  3. Maybe-Monads
  4. List comprehensions
  5. Recursive descent parsers
  6. Continuations
  7. Mini-languages
  8. Parallel computations (PLinq)

Some links:

Combined with fixed-point combinators, Linq provides a complete functional mini-language (Linq raytracer).

Note that Scala and F# both have similar concepts in for-comprehensions and computation expressions both being monadic abstractions:

Scala:

for (x <- expr1
     y <- expr2) yield x + y

F#:

monad {
    let! x = expr1
    let! y = expr2
    return x + y
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...