[m-dev.] Draft collections spec. for library v2
Ralph Becket
rbeck at microsoft.com
Sat Oct 28 01:38:10 AEDT 2000
Comments welcome...
%
----------------------------------------------------------------------------
%
% medison.collections.m
% Ralph Becket <rbeck at microsoft.com>
% Fri Oct 20 13:38:18 BST 2000
% vim: ts=4 sw=4 et tw=0 wm=0 ff=unix
%
% There is an hierarchy of collection types based around whether the
% collection is a set type, a collection of ordered objects, and/or
% a collection of observable objects.
%
% An observable type is one for which two instances that compare as
% equal may still be distinguished by other means (e.g. different
% unordered list representations of the same set).
%
% This makes a difference in that a bag, say, may be implemented using
% run-length encoding for unobservable objects, but not for observable
% objects.
%
% If a collection class does *not* assume that its members are
% observable then the class name takes the suffix `X'.
%
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% coll_x - THE ROOT OF THE HIERARCHY
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
:- type coll(T). % A collection of T objects.
% CONSTRUCTORS
:- func new = coll(T).
:- func singleton(T) = coll(T).
:- func insert(T, coll(T)) = coll(T).
% Without extensions to typeclasses, seq(T) == list(T).
%
:- func insert_seq(seq(T), coll(T)) = coll(T).
:- func union(coll(T), coll(T)) = coll(T).
:- func coll(T) ++ coll(T) = coll(T). % Synonym for union/2.
% XXX Is this necessary? union_seq(S) = foldl(union, new, S).
%
:- func union_seq(seq(coll(T))) = coll(T).
:- func condense(coll(coll(T))) = coll(T).
:- func from_seq(seq(T)) = coll(T).
% REMOVING MEMBERS
:- func delete_one(T, coll(T)) = coll(T).
:- func delete_all(T, coll(T)) = coll(T).
:- func delete_seq(seq(T), coll(T)) = coll(T).
% OBSERVERS
:- pred empty(coll(T)::in) is semidet.
:- func size(coll(T)) = int.
:- pred contains(coll(T)::in, T::in) is semidet.
:- func count(coll(T), T) = int.
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% ord_coll_x < coll_x - ORDERED COLLECTIONS
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% CONSTRUCTORS
% These functions exist to cover the cases where the programmer
% guarantees that the new member has the appropriate property and
% that testing for it at runtime is too costly.
%
:- func unsafe_insert_min(T, coll(T)) = coll(T).
:- func unsafe_insert_max(T, coll(T)) = coll(T).
% The sequence is assumed to be in non-decreasing order.
%
:- func unsafe_from_ord_seq(seq(T)) = coll(T).
% Assumes all items in the first ordered collection are =< the
% items in the second ordered collection.
%
:- func unsafe_append(coll(T), coll(T)) = coll(T).
% REMOVING MEMBERS
% Error if collection is empty.
%
:- func delete_min(coll(T)) = coll(T).
:- func delete_max(coll(T)) = coll(T).
% As above, but no error if collection is empty.
%
:- func safe_delete_min(coll(T)) = coll(T).
:- func safe_delete_max(coll(T)) = coll(T).
% FILTERS AND PARTITIONS
% These allow for more efficient use of built-in comparison functions.
% XXX Shouldn't deforestation remove higher order calls anyway?
:- func filter_lt(T, coll(T)) = coll(T).
:- func filter_le(T, coll(T)) = coll(T).
:- func filter_gt(T, coll(T)) = coll(T).
:- func filter_ge(T, coll(T)) = coll(T).
:- pred partition_lt_ge(T::in, coll(T)::in, coll(T)::out, coll(T)::out) is
det.
:- pred partition_le_gt(T::in, coll(T)::in, coll(T)::out, coll(T)::out) is
det.
:- pred partition_lt_gt(T::in, coll(T)::in, coll(T)::out, coll(T)::out) is
det.
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% set_x < coll_x - SET COLLECTIONS
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% SET OPERATIONS
:- func intersection(coll(T), coll(T)) = coll(T).
:- func difference(coll(T), coll(T)) = coll(T).
% subset(S1, S2) succeeds iff all members of S2 are members of S1.
%
:- pred subset(coll(T)::in, coll(T)::in) is semidet.
% As above, but S1 must contain a member not in S2.
%
:- pred proper_subset(coll(T)::in, coll(T)::in) is semidet.
% Nondeterministically enumerate subsets of a set.
%
:- pred choose_subset(coll(T)::in, coll(T)::out) is multi.
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% ord_set_x < ord_coll_x, set_x - ORDERED SET COLLECTIONS
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% JUST AN ABBREVIATION FOR THE ABOVE DEPENDENCY
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% coll < coll_x - OBSERVABLE COLLECTIONS
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% OBSERVERS
% Find all members in the collection equivalent to a given value.
%
:- func equivalent_members(T, coll(T)) = seq(T).
:- func to_seq(coll(T)) = seq(T).
% FILTERS AND PARTITIONS
:- func filter(pred(T), coll(T)) = coll(T).
:- mode filter(pred(in) is semidet, in) = out is det.
:- pred partition(pred(T) is semidet, coll(T), coll(T), coll(T)).
:- mode partition(pred(in) is semidet, in, out, out) is det.
% FOLDS
:- func fold(func(T1, T2) = T2, T2, coll(T1)) = T2.
:- func fold_1(func(T1, T1) = T1, T1, coll(T1)) = T1.
% MAPPING
:- func map(func(T1) = T2, coll(T1)) = coll(T2).
:- func partial_map(func(T1) = T2, coll(T1)) = coll(T2).
:- mode partial_map(func(in) = out is semidet, in) = out is det.
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% ord_coll < ord_coll_x, coll - OBSERVABLE ORDERED COLLECTIONS
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% DESTRUCTORS
:- func min_member(coll(T)) = T.
:- func max_member(coll(T)) = T.
:- pred min_member_and_rest(coll(T)::in, T::out, coll(T)::out) is semidet.
:- pred max_member_and_rest(coll(T)::in, T::out, coll(T)::out) is semidet.
:- pred min_member_and_rest_det(coll(T)::in, T::out, coll(T)::out) is det.
:- pred max_member_and_rest_det(coll(T)::in, T::out, coll(T)::out) is det.
% OBSERVERS
:- func to_ord_seq(coll(T)) = seq(T).
% FOLDS
:- func foldl(func(T1, T2), T2, coll(T1)) = T2.
:- func foldr(func(T1, T2), T2, coll(T1)) = T2.
:- func foldl_1(func(T1, T1), T1, coll(T1)) = T1.
:- func foldr_1(func(T1, T1), T1, coll(T1)) = T1.
% MAPPING
% The function argument must satisfy the property
%
% all [X, Y] (X =< Y => f(X) =< f(Y))
%
:- func unsafe_monotonic_map(func(T1) = T2, coll(T1)) = coll(T2).
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% set < set_x, coll - OBSERVABLE SET COLLECTIONS
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% The `_with' functions take a function argument which decides which of
% two equivalent objects is to be kept.
% XXX Are these really worth it?
:- type select_fn(T)
== ( func(T, T) = T ).
:- func insert_with(select_fn(T), T, coll(T)) = coll(T).
:- func insert_seq_with(select_fn(T), seq(T), coll(T)) = coll(T).
% Union operations with priority given to members of the
% left/right collection:
%
% union_l(S1, S2) = union_with(func(X, _) = X, S1, S2)
% union_r(S1, S2) = union_with(func(_, Y) = Y, S1, S2)
%
:- func union_l(coll(T), coll(T)) = coll(T).
:- func union_r(coll(T), coll(T)) = coll(T).
:- func union_with(select_fn(T), coll(T), coll(T)) = coll(T).
:- func union_seq_with(select_fn(T), seq(coll(T))) = coll(T).
:- func from_seq_with(select_fn(T), seq(T)) = coll(T).
:- func intersection_l(coll(T), coll(T)) = coll(T).
:- func intersection_r(coll(T), coll(T)) = coll(T).
:- func intersection_with(select_fn(T), coll(T), coll(T)) = coll(T).
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% ord_set < ord_coll, set - OBSERVABLE ORDERED SETS
%
----------------------------------------------------------------------------
%
%
----------------------------------------------------------------------------
%
% Just an abbreviation.
--
Ralph Becket | MSR Cambridge | rbeck at microsoft.com
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list