In addition to the query builder for the Rx Framework listed in @pad, there is also a talk from Wonseok Chae from the F # team about computations that include querying expressions. I'm not sure if the recording was recorded, but there are very detailed slides with a cool example of query syntax for generating .NET IL code.
The source code for the standard F # query constructor is probably the best resource for defining types of operations and compiling them with attributes.
The key attributes you'll probably need are the where clause:
[<CustomOperation("where",MaintainsVariableSpace=true,AllowIntoPattern=true)>] member Where : : source:QuerySource<'T,'Q> * [<ProjectionParameter>] predicate:('T -> bool) -> QuerySource<'T,'Q>
The CustomOperation attribute defines the name of the operation. The (rather important) parameter MaintainsVariableSpace lets you say that the operation returns the same values ββas it did as input. In this case, the variables defined earlier are still available after the operation. For example:
query { for p in db.Products do let name = p.ProductName where (p.UnitPrice.Value > 100.0M) select name }
Here the p and name variables are still available after where , because where only filters the input, but does not convert the values ββto a list.
Finally, ProjectionParameter allows you to say that p.UnitValue > 100.0M should actually be turned into a function that takes a context (available variables) and evaluates this expression. If you do not specify this attribute, then the operation will simply get the value of the argument, as in:
query { for p in .. do take 10 }
Here, argument 10 is just a simple expression that cannot use the values ββin p .
Tomas petricek
source share