123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183(* This file is part of 'travesty'.
Copyright (c) 2018 by Matt Windsor
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. *)(** Extension signatures for containers.
This module contains various signatures that enumerate extensions
that apply to Core containers of both {{!Extensions0}arity 0} and
{{!Extensions1}arity 1}. *)openBase(** {2:generic Generic extensions}
As is often the case in [Travesty], we define an arity-generic
signature first, then specialise it for arity-0 and arity-1
containers. *)moduletypeGeneric_extensions=sigincludeTypes_intf.Generic(** [Generic_extensions] refers to the container type as ['a t],
and the element type as ['a elt]; substitute [t]/[elt]
(arity-0) or ['a t]/['a] (arity-1) accordingly below. *)(** {3 Testing for a specific number of elements}
The following functions help in checking whether a container
has a particular, commonly-required number of elements (zero or
one, one, two, and so on).
*)valat_most_one:'at->'aeltoptionOr_error.t(** [at_most_one xs] returns [Ok None] if [xs] is empty;
[Ok Some(x)] if it contains only [x];
and an error otherwise.
Examples:
{[
T_list.at_most_one [] (* ok None *)
at_most_one [1] (* ok (Some 1) *)
at_most_one [1; 2] (* error -- too many *)
]}
*)valone:'at->'aeltOr_error.t(** [one xs] returns [Ok x] if [xs] contains only [x],
and an error otherwise.
Examples:
{[
T_list.one [] (* error -- not enough *)
one [1] (* ok 1 *)
one [1; 2] (* error -- too many *)
]}
*)valtwo:'at->('aelt*'aelt)Or_error.t(** [two xs] returns [Ok (x, y)] if [xs] is a list containing only [x]
and [y] in that order, and an error otherwise.
Examples:
{[
T_list.two [] (* error -- not enough *)
two [1] (* error -- not enough *)
two [1; 2] (* ok (1, 2) *)
two [1; 2; 3] (* error -- too many *)
]}
*)(** {3 Miscellaneous extensions} *)valmax_measure:measure:('aelt->int)->?default:int->'at->int(** [max_measure ~measure ~default xs] measures each item in [xs]
according to [measure], and returns the highest measure reported.
If [xs] is empty, return [default] if given, and [0]
otherwise. *)end(** {3 Containers of predicates}
The following functions concern containers of predicates
(functions of type ['a -> bool]). *)moduletypeGeneric_predicate_extensions=sigtype'at(** The generic type of predicate containers. *)type'aitem(** The generic type of predicate target elements. *)valany:'aitem->predicates:'at->bool(** [any x ~predicates] tests [x] against [predicates] until one
returns [true], in which case it returns [true];
or all return [false], in which case it returns [false]. *)valall:'aitem->predicates:'at->bool(** [any x ~predicates] tests [x] against [predicates] until one
returns [false], in which case it returns [false];
or all return [true], in which case it returns [true]. *)valnone:'aitem->predicates:'at->bool(** [none x ~predicates] is the same as [any x] with all predicates
in [predicates] negated. It tests [x] against [predicates] until
one returns [true], in which case it returns [false]; or all
return [false], in which case it returns [true]. *)end(** {2:a0 Arity-0 container extensions}
These extensions target arity-0 containers (implementations of
[Container.S0]).
*)(** Extensions for a [Container.S0].
This signature contains the generic extensions outlined in
{{!Generic_extensions}Generic_extensions}. *)moduletypeExtensions0=sigincludeTypes_intf.S0includeGeneric_extensionswithtype'at:=tandtype'aelt:=eltend(** Extensions for a [Container.S0] whose elements are predicates.
This signature extends and constrains {{!Extensions0}Extensions0}. *)moduletypeExtensions0_predicate=sigtypet(** Type of predicate containers *)typeitem(** Type of items being tested against predicates. *)includeExtensions0withtypet:=tandtypeelt:=(item->bool)includeGeneric_predicate_extensionswithtype'at:=tandtype'aitem:=itemend(** {2:a1 Arity-1 container extensions}
These extensions target arity-1 containers (implementations of
[Container.S1]).
*)(** Extensions for a [Container.S1].
This signature contains both the generic extensions outlined in
{{!Generic_extensions}Generic_extensions} as well as extensions
that require the ability to change the element type mid-flight. *)moduletypeExtensions1=sigtype'at(** The type of the container to extend. *)includeGeneric_extensionswithtype'at:='atandtype'aelt:='aincludeGeneric_predicate_extensionswithtype'at:=('a->bool)tandtype'aitem:='a(** Predicate extensions are available on all arity-1 containers,
provided that we fix the element type parameter to ['a -> bool]. *)end