2. Languages
Theory
Relational algebra
Monads and comprehensions
Haskell and Links
Monad comprehensions
Comprehensions with group and order
C# and F#
Language integrated query (LINQ)
Extensible query syntax in F# 3.0
3. Problems
Expressing queries
What operations can we use?
What is the right syntax for queries?
Should the syntax be extensible?
Compiling queries
How to turn normal code to SQL?
How to turn normal code to efficient SQL?
Dealing with functions in SQL code
6. Monad comprehensions
[ p.Name | p <- db.Products, p.Price > 10 ]
db.Products `bind` (p ->
if (p.Price > 10) then return p.Name
else zero)
7. Monadic bind and joins
Join using comprehensions
[ (p.Name, c.CategoryName)
| p <- db.Products, c <- db.Categories
, p.CategoryID = c.ID ]
Translation using monads
db.Products `bind` (p ->
db.Categories `bind` (c ->
if (p.CategoryID = c.ID) then
return (p.Name, c.CategoryName)
else zero))
Multiple uses of bind are nested
Second data source may depend on values from first!
8. Comparing bind and join
Standard join
Two independent data sources
Equality condition on some projected values
[ (p, c) | p <- db.Products, c <- db.Categories
, p.CategoryID = c.ID ]
But bind allows more
Second data source may depend on first
Can use arbitrary conditions
[ (p1.Name, p2.Name)
| p1 <- Products
, p2 <- [ p | p <- Products, p.Price > p1.Price ] ]
10. Adding ordering and grouping
[ p | p <- db.Products, then reverse ]
[ p | p <- db.Products, then order by p.Price ]
[ p | …, then group by p.CategoryID ]
[ p | …, then group by p.CategoryID using groupAdj ]
12. LINQ Overview
Query example
from p in db.Products
join c in db.Categories on p.CategoryID equals c.ID
select new { p.Name, c.CategoryName }
Translating to SQL
All operations have a corresponding method
db.Products.Where(p => p.Price > 10)
db.Products.Select(p => p.Name)
Lambda function translated as expression tree
Expression trees composed and processed
13. Expressing queries
Selection and projection
from p in db.Products where p.Price > 10 select p
from p in db.Products select p.Name
Ordering
from p in db.Products orderby p.Price select p
Grouping
from p in db.Products group p by p.CategoryID
Joins (products with selection)
from p in db.Products
join c in db.Categories on p.CategoryID equals c.ID
select new { ... }
14. Customizing LINQ operators
Operations depend on the data source
Syntax is translated to method calls
from p in db.Products group p by p.CategoryID
db.Products.GroupBy(p => p.CategoryID)
Wrap collection and then use different operator
from p in db.Products.WithAdjacentGrouping()
group p by p.CategoryID
WithAdjacentGrouping : IE<T> -> IEWithGroup<T>
GroupBy : IEWithGroup<T> -> IEWithGroup<IEWithGroup<T>>
Various applications
LINQ over events, Parallel implementation
15. Writing joins in LINQ
Syntax for joins
Independent sources; equality condition only
from p in db.Products
join c in db.Categories on p.CategoryID equals c.ID
select …
Using multiple from clauses
Later from can depend on previous variables
We can write arbitrary conditions
from p in db.Products
from c in db.Categories.Where(c => p.CategoryID == c.ID)
where c.Name != "Stuff"
16. Joins and theory
Multiple from clauses
Uses an operation similar to Bind
SelectMany : M<S> -> (S -> M<C>) -> (S * C -> R) -> M<R>
Can be implemented using Bind
Bind : M<S> -> (S -> M<R>) -> M<R>
StrengthL : V * M<S> -> M<V * S>
Syntax for joins
Can be defined using SelectMany, but not vice versa
Join : M<A> -> M<B> -> (A -> K) -> (B -> K)
-> (A * B -> R) -> M<R>
Resembles operation of “applicative functors”
18. Queries in F# 3.0
Design between Haskell and C#
Can define custom operations
query { for p in db.Products do
orderBy p.Price
takeWhile (p.Price > 100) }
Here orderBy and takeWhile are not built-in
Two kinds of custom operations
Preserve variable scope (orderBy, where, …)
Require re-binding (groupBy)
19. What can be done in F# 3.0?
Better queries for OData
Open standard for REST based queries
Supports only subset of query operations
Expanding dependent tables explicitly
query { for title in db.Movies do
select title.Awards }
Wrong! We did not say we will use Awards
query { for title in db.Movies do
expand title.Awards
select title.Awards }
Other interesting areas: NoSQL, etc.
21. Possible questions
Advanced type checking
Translating custom functions to SQL
Limiting operations and allowed patterns (OData)
Expressivity
What are other join-like operations?
Aren’t monads and bind too powerful?
Are we missing other important operations?
What else is there than just lists…
Classical problems
Optimizing queries, efficient compilation
22. References
Haskell and comprehensions
Comprehensive Comprehensions:
comprehensions with "Order by" and "Group by"
Bringing Back Monad Comprehensions
Monad Comprehensions:
A Versatile Representation for Queries
LINQ, C# and F#
C# Language Specification
msdn.microsoft.com/en-us/library/bb397676.aspx
tomasp.net/blog/idioms-in-linq.aspx