// Reference assemblies that contain LINQ support for F# #r "FSharp.PowerPack.Linq.dll" open Microsoft.FSharp.Linq // Define the database table structure (in F# 3.0, this would be // generated by a type provider, but for this example, we define the // types explicitly, because the fssnip.net web does not support F# 3.0) type Name = string type Task = string type Employees = { Name : Name } type Tasks = { Name : Name; Task : Task } let employees : seq = failwith "!" let tasks : seq = failwith "!" /// A function that takes name & task and generates F# quotation that /// checks whether the "tasks" database contains a specified pair let performs (name:Name, task:Task) = <@ tasks |> Seq.exists (fun t -> t.Name = name && t.Task = task) @> /// Type representing predicates over employees type Predicate = | Perform of Task | And of Predicate * Predicate | Or of Predicate * Predicate | Not of Predicate /// Function that takes a predicate and generates a quoted F# code /// (that can be translated to SQL), which checks /// whether the predicate holds let rec eval = function | Perform t -> <@ fun n -> %(performs(n, t)) @> | And(p1, p2) -> <@ fun n -> (%(eval p1)) n && (%(eval p2)) n @> | Or(p1, p2) -> <@ fun n -> (%(eval p1)) n || (%(eval p2)) n @> | Not(p) -> <@ fun n -> not ((%(eval p)) n) @> // ERROR: The following does not type check! <@ fun n -> eval p1 n && eval p2 n @> // Construct a predicate and turn it into a quotation let f = eval(Or(Perform("a"),And(Perform("b"),Not(Perform("c"))))) // Run query that selects employees matching the predicate <@ seq { for e in employees do if (%f) e.Name then yield e } @> |> Query.query