anchor.diff:  		Doc = erlang:append_element (Document, Label),
   		erlang:append_element (Doc, Value) end.
   
  --spec merge (document(), document()) -> document().
  +%-spec merge (document(), document()) -> document().
   % First doc overrides second with new fields added at end of second doc
   merge (UpDoc, BaseDoc) ->
   	Fun = fun (Label, Value, Doc) -> update (Label, Value, Doc) end,
   	doc_foldl (Fun, BaseDoc, UpDoc).
   
  --spec append (document(), document()) -> document().
  +%-spec append (document(), document()) -> document().
   % Append two documents together
   append (Doc1, Doc2) -> list_to_tuple (tuple_to_list (Doc1) ++ tuple_to_list (Doc2)).
   
   % Value %
   
  --type value() ::
  -	float() |
  -	utf8() |
  -	document() |
  -	arr() |
  -	bin() |
  -	bfunction() |
  -	uuid() |
  -	md5() |
  -	userdefined() |
  -	objectid() |
  -	boolean() |
  -	unixtime() |
  -	null |
  -	regex() |
  -	javascript() |
  -	atom() |
  -	integer() |
  -	mongostamp() |
  -	minmaxkey().
  +%-type value() :: float() | utf8() | document() | arr() | bin() | bfunction() | uuid() | md5() | userdefined() | objectid() | boolean() | unixtime() | null | regex() | javascript() | atom() | integer() | mongostamp() | minmaxkey().
   
   % Note, No value() can be a tuple with even number of elements because then it would be ambiguous with document(). Therefore all tagged values defined below have odd number of elements.
   
   % Array %
   
  --type arr() :: [value()].
  +%-type arr() :: [value()].
   % Caution, a string() will be interpreted as an array of integers. You must supply strings as utf8 binary, see below.
   
   % String %
   
  --type utf8() :: unicode:unicode_binary().
  +%-type utf8() :: unicode:unicode_binary().
   % binary() representing a string of characters encoded with UTF-8.
   % An Erlang string() is a list of unicode characters (codepoints), but this list must be converted to utf-8 binary for use in Bson. Call utf8/1 to do this, or encode pure ascii literals directly as <<"abc">> and non-pure ascii literals as <<"ac"/utf8>>.
   
  --spec utf8 (unicode:chardata()) -> utf8().
  +%-spec utf8 (unicode:chardata()) -> utf8().
   % Convert string to utf8 binary. string() is a subtype of unicode:chardata().
   utf8 (CharData) -> case unicode:characters_to_binary (CharData) of
   	{error, _Bin, _Rest} -> erlang:error (unicode_error, [CharData]);
   	{incomplete, _Bin, _Rest} -> erlang:error (unicode_incomplete, [CharData]);
   	Bin -> Bin end.
   
  --spec str (unicode:chardata()) -> string().
  +%-spec str (unicode:chardata()) -> string().
   % Convert utf8 binary to string. utf8() is a subtype of unicode:chardata().
   str (CharData) -> case unicode:characters_to_list (CharData) of
   	{error, _Bin, _Rest} -> erlang:error (unicode_error, [CharData]);
  
positive.code: 		true -> Doc end end,
  	list_to_tuple (doc_foldr (Fun, [], Document)).
  
  -spec update (label(), value(), document()) -> document().
  % Replace field with new value, adding to end if new
  update (Label, Value, Document) -> case find (Label, Document) of
  	{Index} -> setelement (Index * 2 + 2, Document, Value);
  
negative.code: -export ([timenow/0, ms_precision/1, secs_to_unixtime/1, unixtime_to_secs/1]).
  -export ([objectid/3, objectid_time/1]).
  
  %-type maybe(A) :: {A} | {}.
  
  % Document %
  
  %-type document() :: tuple(). % {label(), value(), label(), value(), ...}.
  % Conceptually a document is a list of label-value pairs (associative array, dictionary, record). However, for read/write-ability, it is implemented as a flat tuple, ie. the list becomes a tuple and the pair braces are elided, so you just have alternating labels and values where each value is associated with the previous label.
  % To distinguish a tagged value such as {uuid, _} (see value() type below) from a document with field name 'uuid' we made sure all valid tagged value types have an odd number of elements (documents have even number of elements). So actually only {bin, uuid, _} is a valid value, {uuid, _} is a document.
  
  %-type label() :: atom().
  
  %-spec doc_foldl (fun ((label(), value(), A) -> A), A, document()) -> A.
  doc_foldl (Fun, Acc, Doc) -> doc_foldlN (Fun, Acc, Doc, 0, tuple_size (Doc) div 2).
  
  %-spec doc_foldlN (fun ((label(), value(), A) -> A), A, document(), integer(), integer()) -> A.
  % Fold over fields from first index (inclusive) to second index (exclusive), zero-based index.
  doc_foldlN (_, Acc, _, High, High) -> Acc;
  doc_foldlN (Fun, Acc, Doc, Low, High) ->
  	Acc1 = Fun (element (Low * 2 + 1, Doc), element (Low * 2 + 2, Doc), Acc),
  	doc_foldlN (Fun, Acc1, Doc, Low + 1, High).
  
  %-spec doc_foldr (fun ((label(), value(), A) -> A), A, document()) -> A.
  doc_foldr (Fun, Acc, Doc) -> doc_foldrN (Fun, Acc, Doc, 0, tuple_size (Doc) div 2).
  
  %-spec doc_foldrN (fun ((label(), value(), A) -> A), A, document(), integer(), integer()) -> A.
  % Fold over fields from second index (exclusive) to first index (inclusive), zero-based index.
  doc_foldrN (_, Acc, _, Low, Low) -> Acc;
  doc_foldrN (Fun, Acc, Doc, Low, High) ->
  	Acc1 = Fun (element (High * 2 - 1, Doc), element (High * 2, Doc), Acc),
  	doc_foldrN (Fun, Acc1, Doc, Low, High - 1).
  
  %-spec fields (document()) -> [{label(), value()}].
  % Convert document to a list of all its fields
  fields (Doc) -> doc_foldr (fun (Label, Value, List) -> [{Label, Value} | List] end, [], Doc).
  
  %-spec document ([{label(), value()}]) -> document().
  % Convert list of fields to a document
  document (Fields) -> list_to_tuple (flatten (Fields)).
  
  %-spec flatten ([{label(), value()}]) -> [label() | value()].
  % Flatten list by removing tuple constructors
  flatten ([]) -> [];
  flatten ([{Label, Value} | Fields]) -> [Label, Value | flatten (Fields)].
  
  %-spec lookup (label(), document()) -> maybe (value()).
  % Value of field in document if there
  lookup (Label, Doc) -> case find (Label, Doc) of
  	{Index} -> {element (Index * 2 + 2, Doc)};
  	{} -> {} end.
  
  %-spec find (label(), document) -> maybe (integer()).
  % Index of field in document if there
  find (Label, Doc) -> findN (Label, Doc, 0, tuple_size (Doc) div 2).
  
  %-spec findN (label(), document(), integer(), integer()) -> maybe (integer()).
  % Find field index in document from first index (inclusive) to second index (exclusive).
  findN (_Label, _Doc, High, High) -> {};
  findN (Label, Doc, Low, High) -> case element (Low * 2 + 1, Doc) of
  	Label -> {Low};
  	_ -> findN (Label, Doc, Low + 1, High) end.
  
  %-spec at (label(), document()) -> value().
  % Value of field in document, error if missing
  at (Label, Document) -> case lookup (Label, Document) of
  	{} -> erlang:error (missing_field, [Label, Document]);
  	{Value} -> Value end.
  
  %-spec include ([label()], document()) -> document().
  % Project given fields of document
  include (Labels, Document) ->
  	Fun = fun (Label, Doc) -> case lookup (Label, Document) of
  