anchor.diff:  -define(is_map(X), is_map(X)).
   -else.
   -define(is_map(X), false).
  --endif.
  -
  -%% The type hierarchy is defined by types()
  -%% - subtypes are mutually exclusive
  -%% - dynamically created subtypes denoted by
  -%%     {'$dynamic', Tag, Fun}
  -%%   where the actual subtype is derived as {Tag, Fun(Data)}
  -%%   (if Fun(Data) returns false, the next subtype is tried)
  -%% - dynamic subtypes must be last in the list of subtypes
  -
  -%% TODO NB. something like this would be the input to the
  -%% 'decision tree compiler' that outputs code equivalent to
  -%% subtype/2.
  --ifdef(discarded).
  -types() ->
  -    [ {'T'
  -      , [ {numeric, fun erlang:is_number/1}
  -        , {atom, fun erlang:is_atom/1}
  -        , {list, fun erlang:is_list/1}
  -        , {tuple, fun erlang:is_tuple/1}
  -        , {binary, fun erlang:is_binary/1}
  -        ]}
  -    , {numeric
  -      , [ {integer, fun erlang:is_integer/1}
  -        , {float, fun erlang:is_float/1}
  -        ]}
  -    , {list
  -      , [ {empty, fun(L) -> L =:= [] end}
  -        , {str_printable, fun is_str_printable/1}
  -        , {'$dynamic', list, fun length/1}
  -        ]}
  -    , {tuple
  -      , [ {empty, fun(T) -> T =:= {} end}
  -        , {'$dynamic', record, fun dyn_record/1}
  -        , {'$dynamic', tuple, fun size/1}
  -        ]}
  -    , {str_printable
  -      , [ {str_alnum, fun is_str_alnum/1}
  -        ] ++ opt_strlen_stub(getopt(strlen)) }
  -    , {str_alnum
  -      , [ {str_integer, fun is_str_integer/1}
  -        , {str_alpha, fun is_str_alpha/1}
  -        ] ++ opt_strlen_stub(getopt(strlen)) }
  -    ] ++ opt_mag(getopt(mag))
  -      ++ opt_strlen(getopt(strlen)).
   -endif.
   
   %% Category, or "kind", of type.
  
positive.code: %% Tests
  -ifdef(TEST).
  
  char_in_ranges_test() ->
      ?assertNot(char_in_ranges($A, [])),
      ?assertNot(char_in_ranges($A, [{$a, $z}])),
      ?assertNot(char_in_ranges($\n, [{$a, $z}])),
      ?assert(char_in_ranges($\n, [{$a, $z}, $\n])),
      ?assert(char_in_ranges($A, [{$A, $Z}])),
      ?assert(char_in_ranges($A, [{$A, $Z}, {$a, $z}])).
  
  -endif.
  
negative.code: subtype_map(_M) -> '$null'. %% TODO
  -else.
  subtype_map(_M) -> '$null'.
  -endif.
  
  %% Find out whether given (nonempty) list is improper or not.
  