0 people like it.

Composing Queries in F#

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
// 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<Employees> = failwith "!"
let tasks : seq<Tasks> = 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
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Linq
type Name = string

Full name: Script.Name
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
type Task = string

Full name: Script.Task
type Employees =
  {Name: Name;}

Full name: Script.Employees
Multiple items
Employees.Name: Name

--------------------
type Name = string

Full name: Script.Name
type Tasks =
  {Name: Name;
   Task: Task;}

Full name: Script.Tasks
Multiple items
Tasks.Name: Name

--------------------
type Name = string

Full name: Script.Name
Multiple items
Tasks.Task: Task

--------------------
type Task = string

Full name: Script.Task
val employees : seq<Employees>

Full name: Script.employees
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
val tasks : seq<Tasks>

Full name: Script.tasks
val performs : name:Name * task:Task -> Quotations.Expr<bool>

Full name: Script.performs


 A function that takes name & task and generates F# quotation that
 checks whether the "tasks" database contains a specified pair
val name : Name
val task : Task
module Seq

from Microsoft.FSharp.Collections
val exists : predicate:('T -> bool) -> source:seq<'T> -> bool

Full name: Microsoft.FSharp.Collections.Seq.exists
val t : Tasks
Tasks.Name: Name
Tasks.Task: Task
type Predicate =
  | Perform of Task
  | And of Predicate * Predicate
  | Or of Predicate * Predicate
  | Not of Predicate

Full name: Script.Predicate


 Type representing predicates over employees
union case Predicate.Perform: Task -> Predicate
union case Predicate.And: Predicate * Predicate -> Predicate
union case Predicate.Or: Predicate * Predicate -> Predicate
union case Predicate.Not: Predicate -> Predicate
val eval : _arg1:Predicate -> Quotations.Expr<(Name -> bool)>

Full name: Script.eval


 Function that takes a predicate and generates a quoted F# code
 (that can be translated to SQL), which checks
 whether the predicate holds
val t : Task
val n : Name
val p1 : Predicate
val p2 : Predicate
val p : Predicate
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
val n : obj
val f : Quotations.Expr<(Name -> bool)>

Full name: Script.f
val e : Employees
Employees.Name: Name
val query : QueryBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.query
Raw view Test code New version

More information

Link:http://fssnip.net/bQ
Posted:14 years ago
Author:
Tags: