Skip to content
This repository was archived by the owner on Oct 18, 2021. It is now read-only.

Typed Code Quotations Spec

Max Hirschhorn edited this page Aug 2, 2013 · 10 revisions

Shows differences between type-checked and -unchecked versions of code quotations.

type Item = {
    tags : string list
    qty : int
    price : float
    sale : bool
    desc : Desc
    sizes : Size list
    option : unit option
}

and Desc = {
    short : string
    long : string
}

and Size = {
    length : int
    width : int
    height : int
}

Query Selectors

Comparison

$all
module Query =
    let all (x : 'a list) (y : 'a list) : bool = invalidOp "not implemented"

bson <@ fun (x : Item) -> x.tags |> Query.all [ "appliances"; "school"; "book" ] @>
$eq
bson <@ fun (x : Item) -> x.qty = 20 @>
$gt
bson <@ fun (x : Item) -> x.qty > 20 @>
$gte
bson <@ fun (x : Item) -> x.qty >= 20 @>
$in
module Query =
    let in' (x : 'a list) (y : 'a) : bool = invalidOp "not implemented"

bson <@ fun (x : Item) -> x.qty |> Query.in' [ 5; 15 ] @>
$lt
bson <@ fun (x : Item) -> x.qty < 20 @>
$lte
bson <@ fun (x : Item) -> x.qty <= 20 @>
$ne
bson <@ fun (x : Item) -> x.qty <> 20 @>
$nin
module Query =
    let nin (x : 'a list) (y : 'a) : bool = invalidOp "not implemented"

bson <@ fun (x : Item) -> x.qty |> Query.nin [ 5; 15 ] @>

Logical

$or
bson <@ fun (x : Item) -> x.price = 1.99 && (x.qty < 20 || x.sale = true) @>
$and
bson <@ fun (x : Item) -> x.price = 1.99 && x.qty < 20 && x.sale = true @>
$not
bson <@ fun (x : Item) -> not (x.price > 1.99) @>
$nor
module Query =
    let nor (x : bool list) : bool = invalidOp "not implemented"

bson <@ fun (x : Item) -> Query.nor [ x.price = 1.99; x.qty < 20; x.sale = true ] @>

Element

$exists
module Query =
    let exists x : bool = invalidOp "not implemented"
    let nexists x : bool = invalidOp "not implemented"

bson <@ fun (x : Item) -> x.qty |> Query.exists && x.qty |> Query.nin [ 5; 15 ] @>
bson <@ fun (x : Item) -> x.qty |> Query.nexists || x.qty |> Query.in [ 5; 15 ] @>
$mod
bson <@ fun (x : Item) -> x.qty % 4 = 0 @>
$type
module Query =
    let type' (x : BsonType) y : bool = invalidOp "not implemented"

bson <@ fun (x : Item) -> x.price |> Query.type' BsonType.Double @>

JavaScript

$where
module Query =
    let where (x : string) y : bool = invalidOp "not implemented"

bson <@ fun (x : Item) -> x |> Query.where "this.credits == this.debits" @>
$regex
let (=~) input pattern =
    System.Text.RegularExpressions.Regex.IsMatch(input, pattern)

bson <@ fun (x : Item) -> x.desc.short =~ "/acme.*corp/i" @>

Array

$elemMatch
module Query =
    let elemMatch x y : bool = invalidOp "not implemented"

bson <@ fun (x : Item) -> x.sizes |> Query.elemMatch (bson <@ fun (y : Size) -> y.length = 1 && y.width > 1 @>) @>
$size
module Query =
    let size (x : int) y : bool = invalidOp "not implemented"

bson <@ fun (x : Item) -> x.tags |> Query.size 2 @>

Update Operators

Since the update command is able to affect multiple fields with different operations, the return type of the function should be a unit list rather than a bool.

Fields

$inc
// mutable
bson <@ fun (x : Item) -> [ x.qty <- x.qty |> (+) 1 ] @>
bson <@ fun (x : Item) -> [ x.qty <- x.qty + 1 ] @>

bson <@ fun (x : Item) -> [ x.qty <- x.qty |> (-) 2 ] @>
bson <@ fun (x : Item) -> [ x.qty <- x.qty - 2 ] @>

// immutable
bson <@ fun (x : Item) -> { x with qty = x.qty |> (+) 1 } @>
bson <@ fun (x : Item) -> { x with qty = x.qty + 1 } @>

bson <@ fun (x : Item) -> { x with qty = x.qty |> (-) 2 } @>
bson <@ fun (x : Item) -> { x with qty = x.qty - 2 } @>
$rename

No change.

$setOnInsert

TODO. May be unnecessary, given how typically a default record is defined.

$set
// mutable
bson <@ fun (x : Item) -> [ x.qty <- 10 ] @>

// immutable
bson <@ fun (x : Item) -> { x with qty = 10 } @>
$unset

Only makes sense in the context of an option type.

// mutable
bson <@ fun (x : Item) -> [ x.option <- None ] @>

// immutable
bson <@ fun (x : Item) -> { x with option = None } @>

Array Operators

$

Only possible as dynamic invocation.

$addToSet
module Update =
    let addToSet (x : 'a) (y : 'a list) : 'a list = invalidOp "not implemented"

// mutable
bson <@ fun (x : Item) -> [ x.tags <- x.tags |> Update.addToSet "toaster" ] @>

// immutable
bson <@ fun (x : Item) -> { x with tags = x.tags |> Update.addToSet "toaster" } @>
$pop
module Update =
    let popleft (x : 'a list) : 'a list = invalidOp "not implemented"
    let popright (x : 'a list) : 'a list = invalidOp "not implemented"

// mutable
bson <@ fun (x : Item) -> [ x.sizes <- x.sizes |> Update.popleft ] @>
bson <@ fun (x : Item) -> [ x.sizes <- x.sizes |> Update.popright ] @>

// immutable
bson <@ fun (x : Item) -> { x with sizes = x.sizes |> Update.popleft } @>
bson <@ fun (x : Item) -> { x with sizes = x.sizes |> Update.popright } @>
$pull
module Update =
    let pull (x : 'a) (y : 'b list) : 'b list = invalidOp "not implemented"

// mutable
bson <@ fun (x : Item) -> [ x.sizes <- x.sizes |> Update.pull (bson <@ fun (y : Size) -> y.height = 75 @>) ] @>

// immutable
bson <@ fun (x : Item) -> { x with sizes = x.sizes |> Update.pull (bson <@ fun (y : Size) -> y.height = 75 @>) } @>
$pullAll
module Update =
    let pullAll (x : 'a list) (y : 'a list) : 'a list = invalidOp "not implemented"

// mutable
bson <@ fun (x : Item) -> [ x.tags <- x.tags |> Update.pullAll [ "appliances"; "school"; "book" ] ] @>

// immutable
bson <@ fun (x : Item) -> { x with tags = x.tags |> Update.pullAll [ "appliances"; "school"; "book" ] } @>
$push
module Update =
    let push (x : 'a) (y : 'a list) : 'a list = invalidOp "not implemented"

// mutable
bson <@ fun (x : Item) -> [ x.tags <- x.tags |> Update.push "toaster" ] @>

// immutable
bson <@ fun (x : Item) -> { x with tags = x.tags |> Update.push "toaster" } @>

Array Modifiers

$each
module Update =
    let each (x : 'a -> 'a list -> 'a list) (y : 'a list) (z : 'a list) : 'a list = invalidOp "not implemented"

// mutable
bson <@ fun (x : Item) -> [ x.tags <- x.tags |> Update.each Update.addToSet [ "appliances"; "school"; "book" ] ] @>
bson <@ fun (x : Item) -> [ x.tags <- x.tags |> Update.each Update.push [ "appliances"; "school"; "book" ] ] @>

// immutable
bson <@ fun (x : Item) -> { x with tags = x.tags |> Update.each Update.addToSet [ "appliances"; "school"; "book" ] } @>
bson <@ fun (x : Item) -> { x with tags = x.tags |> Update.each Update.push [ "appliances"; "school"; "book" ] } @>
$slice
module Update =
    let slice (x : int) (y : 'a list) : 'a list = invalidOp "not implemented"

// mutable
bson <@ fun (x : Item) -> [ x.tags <- x.tags |> Update.each Update.addToSet [ "appliances"; "school"; "book" ]
                                             |> Update.slice -5 ] @>

bson <@ fun (x : Item) -> [ x.tags <- x.tags |> Update.each Update.push [ "appliances"; "school"; "book" ]
                                             |> Update.slice -5 ] @>

// immutable
bson <@ fun (x : Item) -> { x with tags = x.tags |> Update.each Update.addToSet [ "appliances"; "school"; "book" ]
                                                 |> Update.slice -5 } @>

bson <@ fun (x : Item) -> { x with tags = x.tags |> Update.each Update.push [ "appliances"; "school"; "book" ]
                                                 |> Update.slice -5 } @>
$sort
module Update =
    let sort (x : 'a) (y : 'b list) : 'b list = invalidOp "not implemented"

// mutable
bson <@ fun (x : Item) -> [ x.sizes <- x.sizes |> Update.each Update.push [ { length = 3; width = 8; height = 1 }
                                                                            { length = 4; width = 7; height = 2 }
                                                                            { length = 5; width = 6; height = 4 } ]
                                               |> Update.sort (bson <@ fun (y : BsonDocument) -> y?width = 1 @>)
                                               |> Update.slice -5 ] @>

// immutable
bson <@ fun (x : Item) -> { x with sizes = x.sizes |> Update.each Update.push [ { length = 3; width = 8; height = 1 }
                                                                                { length = 4; width = 7; height = 2 }
                                                                                { length = 5; width = 6; height = 4 } ]
                                                   |> Update.sort (bson <@ fun (y : BsonDocument) -> y?width = 1 @>)
                                                   |> Update.slice -5 } @>

Bitwise

$bit
// mutable
bson <@ fun (x : Item) -> [ x.qty <- x.qty |> (&&&) 5 ] @>
bson <@ fun (x : Item) -> [ x.qty <- x.qty &&& 5 ] @>

bson <@ fun (x : Item) -> [ x.qty <- x.qty |> (|||) 5 ] @>
bson <@ fun (x : Item) -> [ x.qty <- x.qty ||| 5 ] @>

// immutable
bson <@ fun (x : Item) -> { x with qty = x.qty |> (&&&) 5 } @>
bson <@ fun (x : Item) -> { x with qty = x.qty &&& 5 } @>

bson <@ fun (x : Item) -> { x with qty = x.qty |> (|||) 5 } @>
bson <@ fun (x : Item) -> { x with qty = x.qty ||| 5 } @>