Funkcjonalnie używany, LINQ to nic innego jak syntaktyczne uproszczenie wyrażania monad. Linq to Objects (Zrozumienie list - nawet to byłoby już bardzo użyteczne), o którym mówiłeś, to tylko jedna z możliwych aplikacji tego typu (podobna do List-Monad w Haskell).
Jeśli piszesz
from x in expr1
from y in expr2
select x + y
to nic ale
do
x <- expr1
y <- expr2
return $ x + y
w Haskell.
Beton rzeczą, która odbywa się w zależności od zdefiniowanych przez użytkownika LINQ dostawców (przesuwnych metody), z których tylko jedna jest Linq.Enumerable
realizacja udziałem IEnumerable
s.
Dzięki temu można stworzyć zupełnie nową semantykę LINQ dla swoich typów.
Przykład: Biorąc pod uwagę typ, który może się nie powieść (wartości zerowalne), można zdefiniować dostawcę Linq do przeszukiwania nad nim.
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()));
}
}
To teraz pozwalają nam napisać taki kod:
var sum = from x in ReadNumber("x")
from y in ReadNumber("y")
select x + y;
Obliczenia będą tylko zwrócić wartość jeżeli wszystkie obliczenia udało i nie inaczej będzie w pierwszym przypadku braku jednego.
W połączeniu z drzewami ekspresyjnych LINQ może być bardzo mocny i pozwala wyrazić -
- Database dostęp
- Asynchronous przepływu programowe
- Maybe-monad
- listowe Lista
- rekurencyjne Descent Parsery
- Kontynuacje
- Mini języki
- obliczenia równoległe (PLinq)
kilka linków:
W połączeniu z kombinatorami stałoprzecinkowymi, Linq oferuje kompletny funkcjonalny mini-język (Linq raytracer).
Zauważ, że Scala i F # oba mają podobne koncepcje za-listowe i wyrażeń obliczeniowych obie będące monadycznego abstrakcje:
Scala:
for (x <- expr1
y <- expr2) yield x + y
F #:
monad {
let! x = expr1
let! y = expr2
return x + y
}
Dziękuję za informacje. Zajrzę do tych tropów. – Joe
Naprawdę, naprawdę dobre podsumowanie z miłym, łatwym do uchwycenia przykładem. +1 –
Kontynuując na łączu raytracer, oto ten sam raytracer zaimplementowany całkowicie w jednym oświadczeniu LINQ: http://tirania.org/blog/archive/2007/Nov-16.html – JulianR