Next: one_or_more, Previous: mercury_term_parser, Up: Top [Contents]
%--------------------------------------------------% % vim: ts=4 sw=4 et ft=mercury %--------------------------------------------------% % Copyright (C) 1995, 1997, 2000, 2002-2006, 2011 The University of Melbourne. % Copyright (C) 2014-2024 The Mercury team. % This file is distributed under the terms specified in COPYING.LIB. %--------------------------------------------------% % % File: multi_map.m. % Main author: dylan. % Stability: medium. % % This file provides the 'multi_map' ADT. % A map (also known as a dictionary or an associative array) is a collection % of (Key, Value) pairs which allows you to look up any Value given the Key. % A multi_map is similar, but it allows more than one Value for each Key. % Multiple occurrences of the same Value can be associated with a given Key. % % This is implemented almost as a special case of map.m. % %--------------------------------------------------% %--------------------------------------------------% :- module multi_map. :- interface. :- import_module assoc_list. :- import_module list. :- import_module map. :- import_module set. %--------------------------------------------------% :- type multi_map(K, V) == map(K, list(V)). %--------------------------------------------------% % Return an empty multi_map. % :- func init = multi_map(_K, _V). :- pred init(multi_map(_K, _V)::uo) is det. % Check whether the multi_map is empty. % :- pred is_empty(multi_map(_K, _V)::in) is semidet. %--------------------------------------------------% % Check whether the multi_map has an entry for the given key. % :- pred contains(multi_map(K, _V)::in, K::in) is semidet. % Succeed once for each key-value pair in the multi_map. % :- pred member(multi_map(K, V)::in, K::out, V::out) is nondet. % If the multi_map has an entry for the given key, return the % list of corresponding values. % :- pred search(multi_map(K, V)::in, K::in, list(V)::out) is semidet. % If the multi_map has an entry for the given key, % succeed once for each of the corresponding values. % :- pred nondet_search(multi_map(K, V)::in, K::in, V::out) is nondet. % If the multi_map has an entry for the given key, % succeed once for each of the corresponding values. % Otherwise, throw an exception. % :- func lookup(multi_map(K, V), K) = list(V). :- pred lookup(multi_map(K, V)::in, K::in, list(V)::out) is det. % If the multi_map has an entry for the given key, % succeed once for each of the corresponding values. % Otherwise, throw an exception. % :- pred nondet_lookup(multi_map(K, V)::in, K::in, V::out) is nondet. % If the multi_map has an entry for keys with the given value, % succeed once for each of those keys. % % NOTE: The implementation of this predicate is necessarily inefficient, % and so this predicate is intended for non-performance-critical uses only. % :- pred inverse_search(multi_map(K, V)::in, V::in, K::out) is nondet. %--------------------------------------------------% % Add the given key-value pair to the multi_map. % Fail if the key already exists. % :- pred insert(K::in, V::in, multi_map(K, V)::in, multi_map(K, V)::out) is semidet. % Add the given key-value pair to the multi_map. % Throw an exception if the key already exists. % :- func det_insert(multi_map(K, V), K, V) = multi_map(K, V). :- pred det_insert(K::in, V::in, multi_map(K, V)::in, multi_map(K, V)::out) is det. % Add the given key-value pair to the multi_map. % Fail if the key does not already exist. % :- pred update(K::in, V::in, multi_map(K, V)::in, multi_map(K, V)::out) is semidet. % Add the given key-value pair to the multi_map. % Throw an exception if the key does not already exist. % :- func det_update(multi_map(K, V), K, V) = multi_map(K, V). :- pred det_update(K::in, V::in, multi_map(K, V)::in, multi_map(K, V)::out) is det. % Replace the list of values corresponding to the given key. % Fails if the key does not already exist. % :- pred replace(K::in, list(V)::in, multi_map(K, V)::in, multi_map(K, V)::out) is semidet. % Replace the list of values corresponding to the given key. % Throws an exception if the key does not already exist. % :- func det_replace(multi_map(K, V), K, list(V)) = multi_map(K, V). :- pred det_replace(K::in, list(V)::in, multi_map(K, V)::in, multi_map(K, V)::out) is det. % Add the given key-value pair to the multi_map. % (`set' is a synonym for `add'.) % :- func add(multi_map(K, V), K, V) = multi_map(K, V). :- pred add(K::in, V::in, multi_map(K, V)::in, multi_map(K, V)::out) is det. :- func set(multi_map(K, V), K, V) = multi_map(K, V). :- pred set(K::in, V::in, multi_map(K, V)::in, multi_map(K, V)::out) is det. % Add the given value-key pair to the multi_map. % (`reverse_set' is a synonym for `reverse_add'.) % :- func reverse_add(multi_map(K, V), V, K) = multi_map(K, V). :- pred reverse_add(V::in, K::in, multi_map(K, V)::in, multi_map(K, V)::out) is det. :- func reverse_set(multi_map(K, V), V, K) = multi_map(K, V). :- pred reverse_set(V::in, K::in, multi_map(K, V)::in, multi_map(K, V)::out) is det. %--------------------------------------------------% % Delete a key and its corresponding values from a multi_map. % If the key is not present, leave the multi_map unchanged. % :- func delete(multi_map(K, V), K) = multi_map(K, V). :- pred delete(K::in, multi_map(K, V)::in, multi_map(K, V)::out) is det. % Delete the given key-value pair from a multi_map. % If the key-value pair is not present, leave the multi_map unchanged. % :- func delete(multi_map(K, V), K, V) = multi_map(K, V). :- pred delete(K::in, V::in, multi_map(K, V)::in, multi_map(K, V)::out) is det. % Delete a key from a multi_map and return the list of values % previously corresponding to it. % Fail if the key is not present. % :- pred remove(K::in, list(V)::out, multi_map(K, V)::in, multi_map(K, V)::out) is semidet. % Delete a key from a multi_map and return the list of values % previously corresponding to it. % Throw an exception if the key is not present. % :- pred det_remove(K::in, list(V)::out, multi_map(K, V)::in, multi_map(K, V)::out) is det. % Remove the smallest key and its corresponding values from the multi_map. % Fails if the multi_map is empty. % :- pred remove_smallest(K::out, list(V)::out, multi_map(K, V)::in, multi_map(K, V)::out) is semidet. %--------------------------------------------------% % Select takes a multi_map and a set of keys and returns a multi_map % containing only the keys in the set, together with their corresponding % values. % :- func select(multi_map(K, V), set(K)) = multi_map(K, V). :- pred select(multi_map(K, V)::in, set(K)::in, multi_map(K, V)::out) is det. %--------------------------------------------------% % merge(MultiMapA, MultiMapB, MultiMap): % % Merge MultiMapA and MultiMapB so that % % - if a key occurs in both MultiMapA and MultiMapB, then the values % corresponding to that key in MultiMap will be the concatenation % of the values to that key from MultiMapA and MultiMapB; while % - if a key occurs in only one of MultiMapA and MultiMapB, then % the values corresponding to it in that map will be carried over % to MultiMap. % :- func merge(multi_map(K, V), multi_map(K, V)) = multi_map(K, V). :- pred merge(multi_map(K, V)::in, multi_map(K, V)::in, multi_map(K, V)::out) is det. %--------------------------------------------------% % Declaratively, a no-operation. % Operationally, a suggestion that the implementation optimize % the representation of the multi_map, in the expectation that the % following operations will consist of searches and lookups % but (almost) no updates. % :- func optimize(multi_map(K, V)) = multi_map(K, V). :- pred optimize(multi_map(K, V)::in, multi_map(K, V)::out) is det. %--------------------------------------------------% % Convert a multi_map to an association list. % :- func to_flat_assoc_list(multi_map(K, V)) = assoc_list(K, V). :- pred to_flat_assoc_list(multi_map(K, V)::in, assoc_list(K, V)::out) is det. % Convert an association list to a multi_map. % :- func from_flat_assoc_list(assoc_list(K, V)) = multi_map(K, V). :- pred from_flat_assoc_list(assoc_list(K, V)::in, multi_map(K, V)::out) is det. % Convert a multi_map to an association list, with all the values % for each key in one element of the association list. % :- func to_assoc_list(multi_map(K, V)) = assoc_list(K, list(V)). :- pred to_assoc_list(multi_map(K, V)::in, assoc_list(K, list(V))::out) is det. % Convert an association list with all the values for each key % in one element of the list to a multi_map. % :- func from_assoc_list(assoc_list(K, list(V))) = multi_map(K, V). :- pred from_assoc_list(assoc_list(K, list(V))::in, multi_map(K, V)::out) is det. % Convert a sorted association list to a multi_map. % :- func from_sorted_assoc_list(assoc_list(K, list(V))) = multi_map(K, V). :- pred from_sorted_assoc_list(assoc_list(K, list(V))::in, multi_map(K, V)::out) is det. % Convert the corresponding elements of a list of keys and a % list of values (which must be of the same length) to a multi_map. % A key may occur more than once in the list of keys. % Throw an exception if the two lists are not the same length. % :- func from_corresponding_lists(list(K), list(V)) = multi_map(K, V). :- pred from_corresponding_lists(list(K)::in, list(V)::in, multi_map(K, V)::out) is det. % Convert the corresponding elements of a list of keys and a % *list of lists* of values to a multi_map. % A key may *not* occur more than once in the list of keys. % Throw an exception if the two lists are not the same length, % or if a key does occur more than once in the list of keys. % :- func from_corresponding_list_lists(list(K), list(list(V))) = multi_map(K, V). :- pred from_corresponding_list_lists(list(K)::in, list(list(V))::in, multi_map(K, V)::out) is det. %--------------------------------------------------% % Given a list of keys, produce a list of their values in a % specified multi_map. % :- func apply_to_list(list(K), multi_map(K, V)) = list(V). :- pred apply_to_list(list(K)::in, multi_map(K, V)::in, list(V)::out) is det. %--------------------------------------------------% % Given a multi_map, return a list of all the keys in it. % :- func keys(multi_map(K, V)) = list(K). :- pred keys(multi_map(K, V)::in, list(K)::out) is det. % Given a multi_map, return a list of all the keys in it % in sorted order. % :- func sorted_keys(multi_map(K, V)) = list(K). :- pred sorted_keys(multi_map(K, V)::in, list(K)::out) is det. % Given a multi_map, return a list of all the keys in it % as a set % :- func keys_as_set(multi_map(K, V)) = set(K). :- pred keys_as_set(multi_map(K, V)::in, set(K)::out) is det. % Given a multi_map, return a list of all the values in it. % :- func values(multi_map(K, V)) = list(V). :- pred values(multi_map(K, V)::in, list(V)::out) is det. %--------------------------------------------------% % Count the number of keys in the multi_map. % :- func count(multi_map(K, V)) = int. :- pred count(multi_map(K, V)::in, int::out) is det. % Count the number of key-value pairs in the multi_map. % :- func all_count(multi_map(K, V)) = int. :- pred all_count(multi_map(K, V)::in, int::out) is det. %--------------------------------------------------% %--------------------------------------------------%
Next: one_or_more, Previous: mercury_term_parser, Up: Top [Contents]