mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
2449 lines
91 KiB
Mathematica
2449 lines
91 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1993-2012 The University of Melbourne.
|
|
% Copyright (C) 2013-2015, 2017-2026 The Mercury team.
|
|
% This file is distributed under the terms specified in COPYING.LIB.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: map.m.
|
|
% Main author: fjh, conway.
|
|
% Stability: high.
|
|
%
|
|
% This file provides the 'map' abstract data type.
|
|
%
|
|
% A map (also known as a dictionary or an associative array) is a collection
|
|
% of (Key, Value) pairs that allows you to look up any Value given its Key.
|
|
% Each Key has exactly one corresponding Value. (If you want the ability
|
|
% to store more than one Value for a given Key, use either multi_map.m
|
|
% or one_or_more_map.m.)
|
|
%
|
|
% The implementation uses balanced 2-3-4 trees, as provided by tree234.m.
|
|
% Virtually all the predicates in this file just forward the work
|
|
% to the corresponding predicate in tree234.m.
|
|
%
|
|
% Note: 2-3-4 trees do not have a canonical representation for any given map.
|
|
% This means that two maps that represent the same set of key-value pairs
|
|
% may have different internal representations, and that therefore they
|
|
% may fail to unify and may compare as unequal. The reason for the difference
|
|
% in the internal representation is usually that the (Key, Value) pairs were
|
|
% inserted into the two maps in different orders, or that the two maps
|
|
% have a different history of deletions. If you want to know whether
|
|
% two maps contain the same set of (Key, Data) pairs, use the map.equal/2
|
|
% predicate below.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module map.
|
|
:- interface.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
:- import_module set.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type map(_K, _V).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Initial creation of maps.
|
|
%
|
|
|
|
% Create an empty map.
|
|
%
|
|
:- func init = (map(K, V)::uo) is det.
|
|
:- pred init(map(_, _)::uo) is det.
|
|
|
|
% Create a map containing only the given key-value pair.
|
|
%
|
|
:- func singleton(K, V) = map(K, V).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Emptiness tests.
|
|
%
|
|
|
|
% Check whether a map is empty.
|
|
%
|
|
:- pred is_empty(map(_, _)::in) is semidet.
|
|
:- pred is_non_empty(map(_, _)::in) is semidet.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Searching for a key.
|
|
%
|
|
|
|
% Succeed if-and-only-if the map contains the given key.
|
|
%
|
|
:- pred contains(map(K, _V)::in, K::in) is semidet.
|
|
|
|
% Return the value associated with the given key in the map.
|
|
% Fail if the map does not contain that key.
|
|
%
|
|
:- func search(map(K, V), K) = V is semidet.
|
|
% NOTE_TO_IMPLEMENTORS CFF :- pragma obsolete(func(search/2), [search/3]).
|
|
:- pred search(map(K, V)::in, K::in, V::out) is semidet.
|
|
|
|
% Return the value associated with the given key in the map.
|
|
% Throw an exception if the map does not contain that key.
|
|
%
|
|
:- func lookup(map(K, V), K) = V.
|
|
:- pred lookup(map(K, V)::in, K::in, V::out) is det.
|
|
|
|
% Search the map for key-value pairs with the given value.
|
|
%
|
|
:- pred inverse_search(map(K, V)::in, V::in, K::out) is nondet.
|
|
|
|
% Search for a key-value pair using the key. If there is no entry
|
|
% for the given key, returns the pair for the next lower key instead.
|
|
% Fails if there is no key with the given or lower value.
|
|
%
|
|
:- pred lower_bound_search(map(K, V)::in, K::in, K::out, V::out)
|
|
is semidet.
|
|
|
|
% Search for a key-value pair using the key. If there is no entry
|
|
% for the given key, returns the pair for the next lower key instead.
|
|
% Throws an exception if there is no key with the given or lower value.
|
|
%
|
|
:- pred lower_bound_lookup(map(K, V)::in, K::in, K::out, V::out) is det.
|
|
|
|
% Search for a key-value pair using the key. If there is no entry
|
|
% for the given key, returns the pair for the next higher key instead.
|
|
% Fails if there is no key with the given or higher value.
|
|
%
|
|
:- pred upper_bound_search(map(K, V)::in, K::in, K::out, V::out)
|
|
is semidet.
|
|
|
|
% Search for a key-value pair using the key. If there is no entry
|
|
% for the given key, returns the pair for the next higher key instead.
|
|
% Throws an exception if there is no key with the given or higher value.
|
|
%
|
|
:- pred upper_bound_lookup(map(K, V)::in, K::in, K::out, V::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Looking for the minimum and maximum keys.
|
|
%
|
|
|
|
% Return the largest key in the map, if there is one.
|
|
%
|
|
:- func max_key(map(K, V)) = K is semidet.
|
|
% NOTE_TO_IMPLEMENTORS CFF :- pragma obsolete(func(max_key/1), [max_key/2]).
|
|
:- pred max_key(map(K, V)::in, K::out) is semidet.
|
|
|
|
% As above, but throw an exception if there is no largest key.
|
|
%
|
|
:- func det_max_key(map(K, V)) = K.
|
|
|
|
% Return the smallest key in the map, if there is one.
|
|
%
|
|
:- func min_key(map(K,V)) = K is semidet.
|
|
% NOTE_TO_IMPLEMENTORS CFF :- pragma obsolete(func(min_key/1), [min_key/2]).
|
|
:- pred min_key(map(K, V)::in, K::out) is semidet.
|
|
|
|
% As above, but throw an exception if there is no smallest key.
|
|
%
|
|
:- func det_min_key(map(K, V)) = K.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Insertions and deletions.
|
|
%
|
|
|
|
% Insert a new key and corresponding value into a map.
|
|
% Fail if the key already exists.
|
|
%
|
|
:- func insert(map(K, V), K, V) = map(K, V) is semidet.
|
|
% NOTE_TO_IMPLEMENTORS CFF :- pragma obsolete(func(insert/3), [insert/4]).
|
|
:- pred insert(K::in, V::in, map(K, V)::in, map(K, V)::out) is semidet.
|
|
|
|
% Insert a new key and corresponding value into a map.
|
|
% Throw an exception if the key already exists.
|
|
%
|
|
:- func det_insert(map(K, V), K, V) = map(K, V).
|
|
:- pred det_insert(K::in, V::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% Apply det_insert to key - value pairs from corresponding lists.
|
|
%
|
|
:- func det_insert_from_corresponding_lists(map(K, V), list(K), list(V))
|
|
= map(K, V).
|
|
:- pred det_insert_from_corresponding_lists(list(K)::in,
|
|
list(V)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% Apply det_insert to key - value pairs from an assoc_list.
|
|
%
|
|
:- func det_insert_from_assoc_list(map(K, V), assoc_list(K, V)) = map(K, V).
|
|
:- pred det_insert_from_assoc_list(assoc_list(K, V)::in,
|
|
map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
%---------------------%
|
|
|
|
% search_insert(K, V, MaybeOldV, !Map):
|
|
%
|
|
% Search for the key K in the map.
|
|
%
|
|
% If the key is already in !.Map, with corresponding value OldV,
|
|
% then set MaybeOldV to yes(OldV), and leave !Map unchanged.
|
|
%
|
|
% If the key is not already in !.Map, then insert it into !Map
|
|
% with value V, and set MaybeOldV to no.
|
|
%
|
|
:- pred search_insert(K::in, V::in, maybe(V)::out,
|
|
map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
%---------------------%
|
|
|
|
% Update the value corresponding to a given key
|
|
% Fail if the key doesn't already exist.
|
|
%
|
|
:- func update(map(K, V), K, V) = map(K, V) is semidet.
|
|
% NOTE_TO_IMPLEMENTORS CFF :- pragma obsolete(func(update/3), [update/4]).
|
|
:- pred update(K::in, V::in, map(K, V)::in, map(K, V)::out) is semidet.
|
|
|
|
% Update the value corresponding to a given key
|
|
% Throw an exception if the key doesn't already exist.
|
|
%
|
|
:- func det_update(map(K, V), K, V) = map(K, V).
|
|
:- pred det_update(K::in, V::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
%---------------------%
|
|
|
|
% If the key is already present update its corresponding value.
|
|
% If the key is not present, insert it with the given value.
|
|
%
|
|
:- func set(map(K, V), K, V) = map(K, V).
|
|
:- pred set(K::in, V::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% Apply set to key - value pairs from corresponding lists.
|
|
%
|
|
:- func set_from_corresponding_lists(map(K, V), list(K), list(V)) = map(K, V).
|
|
:- pred set_from_corresponding_lists(list(K)::in, list(V)::in,
|
|
map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% Apply set to key - value pairs from an assoc_list.
|
|
%
|
|
:- func set_from_assoc_list(map(K, V), assoc_list(K, V)) = map(K, V).
|
|
:- pred set_from_assoc_list(assoc_list(K, V)::in,
|
|
map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
%---------------------%
|
|
|
|
% Delete a key-value pair from a map.
|
|
% If the key is not present, leave the map unchanged.
|
|
%
|
|
:- func delete(map(K, V), K) = map(K, V).
|
|
:- pred delete(K::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% Apply delete/3 to a list of keys.
|
|
%
|
|
:- func delete_list(map(K, V), list(K)) = map(K, V).
|
|
:- pred delete_list(list(K)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% Apply delete/3 to a sorted list of keys. The fact that the list
|
|
% is sorted may make this more efficient. (If the list is not sorted,
|
|
% the predicate or function will either throw an exception or return
|
|
% incorrect output.)
|
|
%
|
|
:- func delete_sorted_list(map(K, V), list(K)) = map(K, V).
|
|
:- pred delete_sorted_list(list(K)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
%---------------------%
|
|
|
|
% Delete a key-value pair from a map and return the value.
|
|
% Fail if the key is not present.
|
|
%
|
|
:- pred remove(K::in, V::out, map(K, V)::in, map(K, V)::out) is semidet.
|
|
|
|
% Delete a key-value pair from a map and return the value.
|
|
% Throw an exception if the key is not present.
|
|
%
|
|
:- pred det_remove(K::in, V::out, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% Remove the smallest item from the map, fail if the map is empty.
|
|
%
|
|
:- pred remove_smallest(K::out, V::out, map(K, V)::in, map(K, V)::out)
|
|
is semidet.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Field selection for maps.
|
|
%
|
|
|
|
% Map ^ elem(Key) = search(Map, Key).
|
|
%
|
|
:- func elem(K, map(K, V)) = V is semidet.
|
|
% NOTE_TO_IMPLEMENTORS CFF :- pragma obsolete(func(elem/2), [search/3]).
|
|
|
|
% Map ^ det_elem(Key) = lookup(Map, Key).
|
|
%
|
|
:- func det_elem(K, map(K, V)) = V.
|
|
|
|
% Field update for maps.
|
|
|
|
% (Map ^ elem(Key) := Value) = set(Map, Key, Value).
|
|
%
|
|
:- func 'elem :='(K, map(K, V), V) = map(K, V).
|
|
|
|
% (Map ^ det_elem(Key) := Value) = det_update(Map, Key, Value).
|
|
%
|
|
:- func 'det_elem :='(K, map(K, V), V) = map(K, V).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Returning keys and values.
|
|
%
|
|
|
|
% Return all the keys in the map, and their corresponding values,
|
|
% one key-value pair at a time.
|
|
%
|
|
:- pred member(map(K, V)::in, K::out, V::out) is nondet.
|
|
|
|
% Given a map, return a list of all the keys in the map.
|
|
%
|
|
:- func keys(map(K, _V)) = list(K).
|
|
:- pred keys(map(K, _V)::in, list(K)::out) is det.
|
|
|
|
% Given a map, return a list of all the keys in the map,
|
|
% in sorted order.
|
|
%
|
|
:- func sorted_keys(map(K, _V)) = list(K).
|
|
:- pred sorted_keys(map(K, _V)::in, list(K)::out) is det.
|
|
|
|
% Given a map, return a list of all the keys in the map,
|
|
% as a set.
|
|
%
|
|
:- func keys_as_set(map(K, _V)) = set(K).
|
|
:- pred keys_as_set(map(K, _V)::in, set(K)::out) is det.
|
|
|
|
% Given a map, return a list of all the values in the map.
|
|
%
|
|
:- func values(map(_K, V)) = list(V).
|
|
:- pred values(map(_K, V)::in, list(V)::out) is det.
|
|
|
|
:- pred keys_and_values(map(K, V)::in, list(K)::out, list(V)::out) is det.
|
|
|
|
% Given a map, succeed if and only if the given list is the list
|
|
% of all the keys in the map.
|
|
% `sorted_keys_match(Map, List)' is equivalent to the conjunction,
|
|
% `sorted_keys(Map, Keys), Keys = List', but it allocates no memory,
|
|
% and it traverses Map only up to the first mismatch.
|
|
%
|
|
:- pred sorted_keys_match(map(K, V)::in, list(K)::in) is semidet.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Operations on values.
|
|
%
|
|
|
|
% Update the value at the given key by applying the supplied
|
|
% transformation to it. Fails if the key is not found. This is faster
|
|
% than first searching for the value and then updating it.
|
|
%
|
|
:- pred transform_value(pred(V, V)::in(pred(in, out) is det), K::in,
|
|
map(K, V)::in, map(K, V)::out) is semidet.
|
|
|
|
% Same as transform_value/4, but throws an exception if the key is not
|
|
% found.
|
|
%
|
|
:- func det_transform_value(func(V) = V, K, map(K, V)) = map(K, V).
|
|
:- pred det_transform_value(pred(V, V)::in(pred(in, out) is det), K::in,
|
|
map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Converting maps to lists.
|
|
%
|
|
|
|
% Convert an association list to a map.
|
|
%
|
|
:- func from_assoc_list(assoc_list(K, V)) = map(K, V).
|
|
:- pred from_assoc_list(assoc_list(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% Convert a sorted association list with no duplicated keys to a map.
|
|
%
|
|
:- func from_sorted_assoc_list(assoc_list(K, V)) = map(K, V).
|
|
:- pred from_sorted_assoc_list(assoc_list(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% Convert a reverse sorted association list with no duplicated keys
|
|
% to a map.
|
|
%
|
|
:- func from_rev_sorted_assoc_list(assoc_list(K, V)) = map(K, V).
|
|
:- pred from_rev_sorted_assoc_list(assoc_list(K, V)::in, map(K, V)::out)
|
|
is det.
|
|
|
|
% Convert a pair of lists (which must be of the same length) to a map.
|
|
%
|
|
:- func from_corresponding_lists(list(K), list(V)) = map(K, V).
|
|
:- pred from_corresponding_lists(list(K)::in, list(V)::in, map(K, V)::out)
|
|
is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Converting lists to maps.
|
|
%
|
|
|
|
% Convert a map to an association list.
|
|
%
|
|
:- func to_assoc_list(map(K, V)) = assoc_list(K, V).
|
|
:- pred to_assoc_list(map(K, V)::in, assoc_list(K, V)::out) is det.
|
|
|
|
% Convert a map to an association list which is sorted on the keys.
|
|
%
|
|
:- func to_sorted_assoc_list(map(K, V)) = assoc_list(K, V).
|
|
:- pred to_sorted_assoc_list(map(K, V)::in, assoc_list(K, V)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Reversing a map.
|
|
%
|
|
|
|
% Consider the original map a set of key-value pairs. This predicate
|
|
% returns a map that maps each value to the set of keys it is paired with
|
|
% in the original map.
|
|
%
|
|
:- func reverse_map(map(K, V)) = map(V, set(K)).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Selecting subsets of maps.
|
|
%
|
|
|
|
% select takes a map and a set of keys, and returns a map
|
|
% containing the keys in the set and their corresponding values.
|
|
%
|
|
:- func select(map(K, V), set(K)) = map(K, V).
|
|
:- pred select(map(K, V)::in, set(K)::in, map(K, V)::out) is det.
|
|
|
|
% select_sorted_list takes a map and a sorted list of keys without
|
|
% duplicates, and returns a map containing the keys in the list
|
|
% and their corresponding values.
|
|
%
|
|
:- func select_sorted_list(map(K, V), list(K)) = map(K, V).
|
|
:- pred select_sorted_list(map(K, V)::in, list(K)::in, map(K, V)::out) is det.
|
|
|
|
% select_unselect takes a map and a set of keys, and returns two maps:
|
|
% the first containing the keys in the set and their corresponding values,
|
|
% the second containing the keys NOT in the set and their corresponding
|
|
% values.
|
|
%
|
|
:- pred select_unselect(map(K, V)::in, set(K)::in,
|
|
map(K, V)::out, map(K, V)::out) is det.
|
|
|
|
% select_unselect_sorted_list takes a map and a sorted list of keys
|
|
% without duplicates, and returns two maps:
|
|
% the first containing the keys in the list and their corresponding values,
|
|
% the second containing the keys NOT in the list and their corresponding
|
|
% values.
|
|
%
|
|
:- pred select_unselect_sorted_list(map(K, V)::in, list(K)::in,
|
|
map(K, V)::out, map(K, V)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Selecting subsets of values.
|
|
%
|
|
|
|
% Given a list of keys, produce a list of their corresponding
|
|
% values in a specified map.
|
|
%
|
|
:- func apply_to_list(list(K), map(K, V)) = list(V).
|
|
:- pred apply_to_list(list(K)::in, map(K, V)::in, list(V)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Operations on two or more maps.
|
|
%
|
|
|
|
% Merge the contents of the two maps.
|
|
% Throws an exception if both sets of keys are not disjoint.
|
|
%
|
|
% The cost of this predicate is proportional to the number of elements
|
|
% in the second map, so for efficiency, you want to put the bigger map
|
|
% first and the smaller map second.
|
|
%
|
|
:- func merge(map(K, V), map(K, V)) = map(K, V).
|
|
:- pred merge(map(K, V)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% For overlay(MapA, MapB, Map), if MapA and MapB both contain the
|
|
% same key, then Map will map that key to the value from MapB.
|
|
% In other words, MapB takes precedence over MapA.
|
|
%
|
|
:- func overlay(map(K, V), map(K, V)) = map(K, V).
|
|
:- pred overlay(map(K, V)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% overlay_large_map(MapA, MapB, Map) performs the same task as
|
|
% overlay(MapA, MapB, Map). However, while overlay takes time
|
|
% proportional to the size of MapB, overlay_large_map takes time
|
|
% proportional to the size of MapA. In other words, it preferable when
|
|
% MapB is the larger map.
|
|
%
|
|
:- func overlay_large_map(map(K, V), map(K, V)) = map(K, V).
|
|
:- pred overlay_large_map(map(K, V)::in, map(K, V)::in, map(K, V)::out)
|
|
is det.
|
|
|
|
%---------------------%
|
|
|
|
% Given two maps MapA and MapB, create a third map CommonMap that
|
|
% has only the keys that occur in both MapA and MapB. For keys
|
|
% that occur in both MapA and MapB, look up the corresponding values.
|
|
% If they are the same, include the key/value pair in CommonMap.
|
|
% If they differ, do not include the key in CommonMap.
|
|
%
|
|
% This predicate effectively considers the input maps to be sets of
|
|
% key/value pairs, computes the intersection of those two sets, and
|
|
% returns the map corresponding to the intersection.
|
|
%
|
|
% common_subset is very similar to intersect, but can succeed
|
|
% even with an output map that does not contain an entry for a key
|
|
% value that occurs in both input maps.
|
|
%
|
|
:- func common_subset(map(K, V), map(K, V)) = map(K, V).
|
|
|
|
% Given two maps MapA and MapB, create a third map, IntersectMap,
|
|
% that has only the keys that occur in both MapA and MapB. For keys
|
|
% that occur in both MapA and MapB, compute the value in the final map
|
|
% by applying the supplied function to the values associated with
|
|
% the key in MapA and MapB.
|
|
%
|
|
:- func intersect(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).
|
|
|
|
% Given two maps MapA and MapB, create a third map, IntersectMap,
|
|
% that has only the keys that occur in both MapA and MapB. For keys
|
|
% that occur in both MapA and MapB, compute the value in the final map
|
|
% by applying the supplied predicate to the values associated with
|
|
% the key in MapA and MapB. Fail if and only if this predicate fails
|
|
% on the values associated with some common key.
|
|
%
|
|
:- pred intersect(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
|
|
:- mode intersect(in(pred(in, in, out) is semidet), in, in, out) is semidet.
|
|
:- mode intersect(in(pred(in, in, out) is det), in, in, out) is det.
|
|
|
|
% Calls intersect. Throws an exception if intersect fails.
|
|
%
|
|
:- func det_intersect((func(V, V) = V)::in(func(in, in) = out is semidet),
|
|
map(K, V)::in, map(K, V)::in) = (map(K, V)::out) is det.
|
|
:- pred det_intersect((pred(V, V, V))::in(pred(in, in, out) is semidet),
|
|
map(K, V)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% intersect_list(Pred, M, Ms, ResultM):
|
|
%
|
|
% Take the non-empty list of maps [M | Ms], and intersect pairs of
|
|
% those maps (using map.intersect above) until there is only one map left.
|
|
% Return this map as ResultM. The order in which those intersect
|
|
% operations are performed is not defined, so the caller should choose
|
|
% a Pred for which the order does not matter.
|
|
%
|
|
:- pred intersect_list(pred(V, V, V), map(K, V), list(map(K, V)), map(K, V)).
|
|
:- mode intersect_list(in(pred(in, in, out) is semidet),
|
|
in, in, out) is semidet.
|
|
:- mode intersect_list(in(pred(in, in, out) is det),
|
|
in, in, out) is det.
|
|
|
|
%---------------------%
|
|
|
|
% Given two maps MapA and MapB, create a third map, UnionMap, that
|
|
% contains all the keys that occur in either MapA or MapB. For keys
|
|
% that occur in both MapA and MapB, compute the value in the final map
|
|
% by applying the supplied function to the values associated with the key
|
|
% in MapA and MapB.
|
|
%
|
|
:- func union(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).
|
|
|
|
% Given two maps MapA and MapB, create a third map, UnionMap, that
|
|
% contains all the keys that occur in either MapA and MapB. For keys
|
|
% that occur in both MapA and MapB, compute the value in the final map
|
|
% by applying the supplied predicate to the values associated with the key
|
|
% in MapA and MapB. Fail if and only if this predicate fails on
|
|
% the values associated with some common key.
|
|
%
|
|
:- pred union(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
|
|
:- mode union(in(pred(in, in, out) is semidet), in, in, out) is semidet.
|
|
:- mode union(in(pred(in, in, out) is det), in, in, out) is det.
|
|
|
|
% Calls union. Throws an exception if union fails.
|
|
%
|
|
:- func det_union((func(V, V) = V)::in(func(in, in) = out is semidet),
|
|
map(K, V)::in, map(K, V)::in) = (map(K, V)::out) is det.
|
|
:- pred det_union(pred(V, V, V)::in(pred(in, in, out) is semidet),
|
|
map(K, V)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
% union_list(Pred, M, Ms, ResultM):
|
|
%
|
|
% Take the non-empty list of maps [M | Ms], and union pairs of those maps
|
|
% (using union above) until there is only one map left. Return this map
|
|
% as ResultM. The order of in which those union operations are performed
|
|
% is not defined, so the caller should choose a Pred for which the order
|
|
% does not matter.
|
|
%
|
|
:- pred union_list(pred(V, V, V), map(K, V), list(map(K, V)), map(K, V)).
|
|
:- mode union_list(in(pred(in, in, out) is semidet), in, in, out) is semidet.
|
|
:- mode union_list(in(pred(in, in, out) is det), in, in, out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Composing two maps.
|
|
%
|
|
|
|
% compose_maps(MapAB, MapBC, MapAC):
|
|
%
|
|
% Given each A - B pair in MapAB, return the map that pairs
|
|
% each such A with the C corresponding to its B in MapBC.
|
|
% Throw an exception if there is no value associated with B in MapBC.
|
|
%
|
|
:- pred compose_maps(map(A, B)::in, map(B, C)::in, map(A, C)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Counting.
|
|
%
|
|
|
|
% Count the number of elements in the map.
|
|
%
|
|
:- func count(map(K, V)) = int.
|
|
:- pred count(map(K, V)::in, int::out) is det.
|
|
:- func ucount(map(K, V)) = uint.
|
|
:- pred ucount(map(K, V)::in, uint::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Comparisons between maps.
|
|
%
|
|
|
|
% True if both maps have the same set of key-value pairs, regardless of
|
|
% how the maps were constructed.
|
|
%
|
|
% Unifying maps does not work as one might expect, because the internal
|
|
% structures of two maps that contain the same set of key-value pairs
|
|
% may be different.
|
|
%
|
|
:- pred equal(map(K, V)::in, map(K, V)::in) is semidet.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Optimization.
|
|
%
|
|
|
|
% Declaratively, a no-operation.
|
|
% Operationally, a suggestion that the implementation
|
|
% optimize the representation of the map in the expectation
|
|
% of a number of lookups but few or no modifications.
|
|
%
|
|
% This operation is here only for "cultural compatibility"
|
|
% with the modules that operate on trees that may be unbalanced.
|
|
% 2-3-4 trees are always guaranteed to be balanced, so they do not need
|
|
% any such optimization.
|
|
%
|
|
:- func optimize(map(K, V)) = map(K, V).
|
|
:- pred optimize(map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Standard higher order functions on collections.
|
|
%
|
|
|
|
|
|
% Perform an inorder traversal of the map, applying
|
|
% an accumulator predicate for each key-value pair.
|
|
%
|
|
:- func foldl(func(K, V, A) = A, map(K, V), A) = A.
|
|
:- pred foldl(pred(K, V, A, A), map(K, V), A, A).
|
|
:- mode foldl(in(pred(in, in, in, out) is det), in, in, out) is det.
|
|
:- mode foldl(in(pred(in, in, mdi, muo) is det), in, mdi, muo) is det.
|
|
:- mode foldl(in(pred(in, in, di, uo) is det), in, di, uo) is det.
|
|
:- mode foldl(in(pred(in, in, in, out) is semidet), in, in, out) is semidet.
|
|
:- mode foldl(in(pred(in, in, mdi, muo) is semidet), in, mdi, muo) is semidet.
|
|
:- mode foldl(in(pred(in, in, di, uo) is semidet), in, di, uo) is semidet.
|
|
:- mode foldl(in(pred(in, in, in, out) is cc_multi), in, in, out) is cc_multi.
|
|
:- mode foldl(in(pred(in, in, di, uo) is cc_multi), in, di, uo) is cc_multi.
|
|
:- mode foldl(in(pred(in, in, mdi, muo) is cc_multi), in, mdi, muo)
|
|
is cc_multi.
|
|
|
|
% Perform an inorder traversal of the map, applying an accumulator
|
|
% predicate with two accumulators for each key-value pair.
|
|
% (Although no more expressive than foldl, this is often
|
|
% a more convenient format, and a little more efficient).
|
|
%
|
|
:- pred foldl2(pred(K, V, A, A, B, B), map(K, V), A, A, B, B).
|
|
:- mode foldl2(in(pred(in, in, in, out, in, out) is det),
|
|
in, in, out, in, out) is det.
|
|
:- mode foldl2(in(pred(in, in, in, out, mdi, muo) is det),
|
|
in, in, out, mdi, muo) is det.
|
|
:- mode foldl2(in(pred(in, in, in, out, di, uo) is det),
|
|
in, in, out, di, uo) is det.
|
|
:- mode foldl2(in(pred(in, in, di, uo, di, uo) is det),
|
|
in, di, uo, di, uo) is det.
|
|
:- mode foldl2(in(pred(in, in, in, out, in, out) is semidet),
|
|
in, in, out, in, out) is semidet.
|
|
:- mode foldl2(in(pred(in, in, in, out, mdi, muo) is semidet),
|
|
in, in, out, mdi, muo) is semidet.
|
|
:- mode foldl2(in(pred(in, in, in, out, di, uo) is semidet),
|
|
in, in, out, di, uo) is semidet.
|
|
:- mode foldl2(in(pred(in, in, in, out, in, out) is cc_multi),
|
|
in, in, out, in, out) is cc_multi.
|
|
:- mode foldl2(in(pred(in, in, in, out, mdi, muo) is cc_multi),
|
|
in, in, out, mdi, muo) is cc_multi.
|
|
:- mode foldl2(in(pred(in, in, in, out, di, uo) is cc_multi),
|
|
in, in, out, di, uo) is cc_multi.
|
|
:- mode foldl2(in(pred(in, in, di, uo, di, uo) is cc_multi),
|
|
in, di, uo, di, uo) is cc_multi.
|
|
|
|
% Perform an inorder traversal of the map, applying an accumulator
|
|
% predicate with three accumulators for each key-value pair.
|
|
% (Although no more expressive than foldl, this is often
|
|
% a more convenient format, and a little more efficient).
|
|
%
|
|
:- pred foldl3(pred(K, V, A, A, B, B, C, C), map(K, V), A, A, B, B, C, C).
|
|
:- mode foldl3(in(pred(in, in, in, out, in, out, in, out) is det),
|
|
in, in, out, in, out, in, out) is det.
|
|
:- mode foldl3(in(pred(in, in, in, out, in, out, mdi, muo) is det),
|
|
in, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldl3(in(pred(in, in, in, out, in, out, di, uo) is det),
|
|
in, in, out, in, out, di, uo) is det.
|
|
:- mode foldl3(in(pred(in, in, in, out, di, uo, di, uo) is det),
|
|
in, in, out, di, uo, di, uo) is det.
|
|
:- mode foldl3(in(pred(in, in, di, uo, di, uo, di, uo) is det),
|
|
in, di, uo, di, uo, di, uo) is det.
|
|
:- mode foldl3(in(pred(in, in, in, out, in, out, in, out) is semidet),
|
|
in, in, out, in, out, in, out) is semidet.
|
|
:- mode foldl3(in(pred(in, in, in, out, in, out, mdi, muo) is semidet),
|
|
in, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldl3(in(pred(in, in, in, out, in, out, di, uo) is semidet),
|
|
in, in, out, in, out, di, uo) is semidet.
|
|
|
|
% Perform an inorder traversal of the map, applying an accumulator
|
|
% predicate with four accumulators for each key-value pair.
|
|
% (Although no more expressive than foldl, this is often
|
|
% a more convenient format, and a little more efficient).
|
|
%
|
|
:- pred foldl4(pred(K, V, A, A, B, B, C, C, D, D), map(K, V),
|
|
A, A, B, B, C, C, D, D).
|
|
:- mode foldl4(
|
|
in(pred(in, in, in, out, in, out, in, out, in, out) is det),
|
|
in, in, out, in, out, in, out, in, out) is det.
|
|
:- mode foldl4(
|
|
in(pred(in, in, in, out, in, out, in, out, mdi, muo) is det),
|
|
in, in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldl4(
|
|
in(pred(in, in, in, out, in, out, in, out, di, uo) is det),
|
|
in, in, out, in, out, in, out, di, uo) is det.
|
|
:- mode foldl4(
|
|
in(pred(in, in, in, out, in, out, di, uo, di, uo) is det),
|
|
in, in, out, in, out, di, uo, di, uo) is det.
|
|
:- mode foldl4(
|
|
in(pred(in, in, in, out, di, uo, di, uo, di, uo) is det),
|
|
in, in, out, di, uo, di, uo, di, uo) is det.
|
|
:- mode foldl4(
|
|
in(pred(in, in, di, uo, di, uo, di, uo, di, uo) is det),
|
|
in, di, uo, di, uo, di, uo, di, uo) is det.
|
|
:- mode foldl4(
|
|
in(pred(in, in, in, out, in, out, in, out, in, out) is semidet),
|
|
in, in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode foldl4(
|
|
in(pred(in, in, in, out, in, out, in, out, mdi, muo) is semidet),
|
|
in, in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldl4(
|
|
in(pred(in, in, in, out, in, out, in, out, di, uo) is semidet),
|
|
in, in, out, in, out, in, out, di, uo) is semidet.
|
|
|
|
% Perform an inorder traversal of the map, applying an accumulator
|
|
% predicate with five accumulators for each key-value pair.
|
|
% (Although no more expressive than foldl, this is often
|
|
% a more convenient format, and a little more efficient).
|
|
%
|
|
:- pred foldl5(pred(K, V, A, A, B, B, C, C, D, D, E, E), map(K, V),
|
|
A, A, B, B, C, C, D, D, E, E).
|
|
:- mode foldl5(in(pred(in, in, in, out, in, out, in, out, in, out, in, out)
|
|
is det),
|
|
in, in, out, in, out, in, out, in, out, in, out) is det.
|
|
:- mode foldl5(in(pred(in, in, in, out, in, out, in, out, in, out, mdi, muo)
|
|
is det),
|
|
in, in, out, in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldl5(in(pred(in, in, in, out, in, out, in, out, in, out, di, uo)
|
|
is det),
|
|
in, in, out, in, out, in, out, in, out, di, uo) is det.
|
|
:- mode foldl5(in(pred(in, in, in, out, in, out, in, out, in, out, in, out)
|
|
is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode foldl5(in(pred(in, in,in, out, in, out, in, out, in, out, mdi, muo)
|
|
is semidet),
|
|
in, in, out, in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldl5(in(pred(in, in, in, out, in, out, in, out, in, out, di, uo)
|
|
is semidet),
|
|
in, in, out, in, out, in, out, in, out, di, uo) is semidet.
|
|
|
|
% Perform an inorder traversal of the map, applying an accumulator
|
|
% predicate with five accumulators for each key-value pair.
|
|
% (Although no more expressive than foldl, this is often
|
|
% a more convenient format, and a little more efficient).
|
|
%
|
|
:- pred foldl6(pred(K, V, A, A, B, B, C, C, D, D, E, E, F, F), map(K, V),
|
|
A, A, B, B, C, C, D, D, E, E, F, F).
|
|
:- mode foldl6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, in, out) is det),
|
|
in, in, out, in, out, in, out, in, out, in, out, in, out) is det.
|
|
:- mode foldl6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, mdi, muo) is det),
|
|
in, in, out, in, out, in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldl6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, di, uo) is det),
|
|
in, in, out, in, out, in, out, in, out, in, out, di, uo) is det.
|
|
:- mode foldl6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, in, out) is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode foldl6(in(pred(in, in,in, out, in, out, in, out, in, out,
|
|
in, out, mdi, muo) is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldl6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, di, uo) is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out, di, uo) is semidet.
|
|
|
|
%---------------------%
|
|
|
|
% Perform an inorder traversal by key of the map, applying an accumulator
|
|
% predicate for value.
|
|
%
|
|
:- pred foldl_values(pred(V, A, A), map(K, V), A, A).
|
|
:- mode foldl_values(in(pred(in, in, out) is det), in, in, out) is det.
|
|
:- mode foldl_values(in(pred(in, mdi, muo) is det), in, mdi, muo) is det.
|
|
:- mode foldl_values(in(pred(in, di, uo) is det), in, di, uo) is det.
|
|
:- mode foldl_values(in(pred(in, in, out) is semidet), in, in, out) is semidet.
|
|
:- mode foldl_values(in(pred(in, mdi, muo) is semidet), in, mdi, muo)
|
|
is semidet.
|
|
:- mode foldl_values(in(pred(in, di, uo) is semidet), in, di, uo) is semidet.
|
|
:- mode foldl_values(in(pred(in, in, out) is cc_multi), in, in, out)
|
|
is cc_multi.
|
|
:- mode foldl_values(in(pred(in, di, uo) is cc_multi), in, di, uo) is cc_multi.
|
|
:- mode foldl_values(in(pred(in, mdi, muo) is cc_multi), in, mdi, muo)
|
|
is cc_multi.
|
|
|
|
% As above, but with two accumulators.
|
|
%
|
|
:- pred foldl2_values(pred(V, A, A, B, B), map(K, V), A, A, B, B).
|
|
:- mode foldl2_values(in(pred(in, in, out, in, out) is det), in,
|
|
in, out, in, out) is det.
|
|
:- mode foldl2_values(in(pred(in, in, out, mdi, muo) is det), in,
|
|
in, out, mdi, muo) is det.
|
|
:- mode foldl2_values(in(pred(in, in, out, di, uo) is det), in,
|
|
in, out, di, uo) is det.
|
|
:- mode foldl2_values(in(pred(in, in, out, in, out) is semidet), in,
|
|
in, out, in, out) is semidet.
|
|
:- mode foldl2_values(in(pred(in, in, out, mdi, muo) is semidet), in,
|
|
in, out, mdi, muo) is semidet.
|
|
:- mode foldl2_values(in(pred(in, in, out, di, uo) is semidet), in,
|
|
in, out, di, uo) is semidet.
|
|
:- mode foldl2_values(in(pred(in, in, out, in, out) is cc_multi), in,
|
|
in, out, in, out) is cc_multi.
|
|
:- mode foldl2_values(in(pred(in, in, out, mdi, muo) is cc_multi), in,
|
|
in, out, mdi, muo) is cc_multi.
|
|
:- mode foldl2_values(in(pred(in, in, out, di, uo) is cc_multi), in,
|
|
in, out, di, uo) is cc_multi.
|
|
|
|
% As above, but with three accumulators.
|
|
%
|
|
:- pred foldl3_values(pred(V, A, A, B, B, C, C), map(K, V),
|
|
A, A, B, B, C, C).
|
|
:- mode foldl3_values(in(pred(in, in, out, in, out, in, out) is det), in,
|
|
in, out, in, out, in, out) is det.
|
|
:- mode foldl3_values(in(pred(in, in, out, in, out, mdi, muo) is det), in,
|
|
in, out, in, out, mdi, muo) is det.
|
|
:- mode foldl3_values(in(pred(in, in, out, in, out, di, uo) is det), in,
|
|
in, out, in, out, di, uo) is det.
|
|
:- mode foldl3_values(in(pred(in, in, out, in, out, in, out) is semidet), in,
|
|
in, out, in, out, in, out) is semidet.
|
|
:- mode foldl3_values(in(pred(in, in, out, in, out, mdi, muo) is semidet), in,
|
|
in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldl3_values(in(pred(in, in, out, in, out, di, uo) is semidet), in,
|
|
in, out, in, out, di, uo) is semidet.
|
|
:- mode foldl3_values(in(pred(in, in, out, in, out, in, out) is cc_multi), in,
|
|
in, out, in, out, in, out) is cc_multi.
|
|
:- mode foldl3_values(in(pred(in, in, out, in, out, mdi, muo) is cc_multi), in,
|
|
in, out, in, out, mdi, muo) is cc_multi.
|
|
:- mode foldl3_values(in(pred(in, in, out, in, out, di, uo) is cc_multi), in,
|
|
in, out, in, out, di, uo) is cc_multi.
|
|
|
|
%---------------------%
|
|
|
|
% As above, but with four accumulators.
|
|
%
|
|
:- pred foldl4_values(pred(V, A, A, B, B, C, C, D, D), map(K, V),
|
|
A, A, B, B, C, C, D, D).
|
|
:- mode foldl4_values(in(pred(in, in, out, in, out, in, out, in, out) is det),
|
|
in, in, out, in, out, in, out, in, out) is det.
|
|
:- mode foldl4_values(in(pred(in, in, out, in, out, in, out, mdi, muo) is det),
|
|
in, in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldl4_values(in(pred(in, in, out, in, out, in, out, di, uo) is det),
|
|
in, in, out, in, out, in, out, di, uo) is det.
|
|
:- mode foldl4_values(in(pred(in, in, out, in, out, di, uo, di, uo) is det),
|
|
in, in, out, in, out, di, uo, di, uo) is det.
|
|
:- mode foldl4_values(in(pred(in, in, out, di, uo, di, uo, di, uo) is det),
|
|
in, in, out, di, uo, di, uo, di, uo) is det.
|
|
:- mode foldl4_values(in(pred(in, di, uo, di, uo, di, uo, di, uo) is det),
|
|
in, di, uo, di, uo, di, uo, di, uo) is det.
|
|
:- mode foldl4_values(in(pred(in, in, out, in, out, in, out, in, out) is
|
|
semidet),
|
|
in, in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode foldl4_values(in(pred(in, in, out, in, out, in, out, mdi, muo) is
|
|
semidet),
|
|
in, in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldl4_values(in(pred(in, in, out, in, out, in, out, di, uo) is
|
|
semidet),
|
|
in, in, out, in, out, in, out, di, uo) is semidet.
|
|
|
|
% As above, but with five accumulators.
|
|
%
|
|
:- pred foldl5_values(pred(V, A, A, B, B, C, C, D, D, E, E), map(K, V),
|
|
A, A, B, B, C, C, D, D, E, E).
|
|
:- mode foldl5_values(in(pred(in, in, out, in, out, in, out, in, out, in, out)
|
|
is det),
|
|
in, in, out, in, out, in, out, in, out, in, out) is det.
|
|
:- mode foldl5_values(in(pred(in, in, out, in, out, in, out, in, out, mdi, muo)
|
|
is det),
|
|
in, in, out, in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldl5_values(in(pred(in, in, out, in, out, in, out, in, out, di, uo)
|
|
is det),
|
|
in, in, out, in, out, in, out, in, out, di, uo) is det.
|
|
:- mode foldl5_values(in(pred(in, in, out, in, out, in, out, in, out, in, out)
|
|
is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode foldl5_values(in(pred(in,in, out, in, out, in, out, in, out, mdi, muo)
|
|
is semidet),
|
|
in, in, out, in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldl5_values(in(pred(in, in, out, in, out, in, out, in, out, di, uo)
|
|
is semidet),
|
|
in, in, out, in, out, in, out, in, out, di, uo) is semidet.
|
|
|
|
% As above, but with five accumulators.
|
|
%
|
|
:- pred foldl6_values(pred(V, A, A, B, B, C, C, D, D, E, E, F, F), map(K, V),
|
|
A, A, B, B, C, C, D, D, E, E, F, F).
|
|
:- mode foldl6_values(in(pred(in, in, out, in, out, in, out, in, out,
|
|
in, out, in, out) is det),
|
|
in, in, out, in, out, in, out, in, out, in, out, in, out) is det.
|
|
:- mode foldl6_values(in(pred(in, in, out, in, out, in, out, in, out,
|
|
in, out, mdi, muo) is det),
|
|
in, in, out, in, out, in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldl6_values(in(pred(in, in, out, in, out, in, out, in, out,
|
|
in, out, di, uo) is det),
|
|
in, in, out, in, out, in, out, in, out, in, out, di, uo) is det.
|
|
:- mode foldl6_values(in(pred(in, in, out, in, out, in, out, in, out,
|
|
in, out, in, out) is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode foldl6_values(in(pred(in,in, out, in, out, in, out, in, out,
|
|
in, out, mdi, muo) is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldl6_values(in(pred(in, in, out, in, out, in, out, in, out,
|
|
in, out, di, uo) is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out, di, uo) is semidet.
|
|
|
|
:- func foldr(func(K, V, A) = A, map(K, V), A) = A.
|
|
:- pred foldr(pred(K, V, A, A), map(K, V), A, A).
|
|
:- mode foldr(in(pred(in, in, in, out) is det), in, in, out) is det.
|
|
:- mode foldr(in(pred(in, in, mdi, muo) is det), in, mdi, muo) is det.
|
|
:- mode foldr(in(pred(in, in, di, uo) is det), in, di, uo) is det.
|
|
:- mode foldr(in(pred(in, in, in, out) is semidet), in, in, out) is semidet.
|
|
:- mode foldr(in(pred(in, in, mdi, muo) is semidet), in, mdi, muo) is semidet.
|
|
:- mode foldr(in(pred(in, in, di, uo) is semidet), in, di, uo) is semidet.
|
|
:- mode foldr(in(pred(in, in, in, out) is cc_multi), in, in, out) is cc_multi.
|
|
:- mode foldr(in(pred(in, in, mdi, muo) is cc_multi), in, mdi, muo)
|
|
is cc_multi.
|
|
:- mode foldr(in(pred(in, in, di, uo) is cc_multi), in, di, uo) is cc_multi.
|
|
|
|
:- pred foldr2(pred(K, V, A, A, B, B), map(K, V), A, A, B, B).
|
|
:- mode foldr2(in(pred(in, in, in, out, in, out) is det),
|
|
in, in, out, in, out) is det.
|
|
:- mode foldr2(in(pred(in, in, in, out, mdi, muo) is det),
|
|
in, in, out, mdi, muo) is det.
|
|
:- mode foldr2(in(pred(in, in, in, out, di, uo) is det),
|
|
in, in, out, di, uo) is det.
|
|
:- mode foldr2(in(pred(in, in, di, uo, di, uo) is det),
|
|
in, di, uo, di, uo) is det.
|
|
:- mode foldr2(in(pred(in, in, in, out, in, out) is semidet),
|
|
in, in, out, in, out) is semidet.
|
|
:- mode foldr2(in(pred(in, in, in, out, mdi, muo) is semidet),
|
|
in, in, out, mdi, muo) is semidet.
|
|
:- mode foldr2(in(pred(in, in, in, out, di, uo) is semidet),
|
|
in, in, out, di, uo) is semidet.
|
|
|
|
:- pred foldr3(pred(K, V, A, A, B, B, C, C), map(K, V), A, A, B, B, C, C).
|
|
:- mode foldr3(in(pred(in, in, in, out, in, out, in, out) is det),
|
|
in, in, out, in, out, in, out) is det.
|
|
:- mode foldr3(in(pred(in, in, in, out, in, out, mdi, muo) is det),
|
|
in, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldr3(in(pred(in, in, in, out, in, out, di, uo) is det),
|
|
in, in, out, in, out, di, uo) is det.
|
|
:- mode foldr3(in(pred(in, in, in, out, di, uo, di, uo) is det),
|
|
in, in, out, di, uo, di, uo) is det.
|
|
:- mode foldr3(in(pred(in, in, di, uo, di, uo, di, uo) is det),
|
|
in, di, uo, di, uo, di, uo) is det.
|
|
:- mode foldr3(in(pred(in, in, in, out, in, out, in, out) is semidet),
|
|
in, in, out, in, out, in, out) is semidet.
|
|
:- mode foldr3(in(pred(in, in, in, out, in, out, mdi, muo) is semidet),
|
|
in, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldr3(in(pred(in, in, in, out, in, out, di, uo) is semidet),
|
|
in, in, out, in, out, di, uo) is semidet.
|
|
|
|
:- pred foldr4(pred(K, V, A, A, B, B, C, C, D, D), map(K, V),
|
|
A, A, B, B, C, C, D, D).
|
|
:- mode foldr4(
|
|
in(pred(in, in, in, out, in, out, in, out, in, out) is det),
|
|
in, in, out, in, out, in, out, in, out) is det.
|
|
:- mode foldr4(
|
|
in(pred(in, in, in, out, in, out, in, out, mdi, muo) is det),
|
|
in, in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldr4(
|
|
in(pred(in, in, in, out, in, out, in, out, di, uo) is det),
|
|
in, in, out, in, out, in, out, di, uo) is det.
|
|
:- mode foldr4(
|
|
in(pred(in, in, in, out, in, out, di, uo, di, uo) is det),
|
|
in, in, out, in, out, di, uo, di, uo) is det.
|
|
:- mode foldr4(
|
|
in(pred(in, in, in, out, di, uo, di, uo, di, uo) is det),
|
|
in, in, out, di, uo, di, uo, di, uo) is det.
|
|
:- mode foldr4(
|
|
in(pred(in, in, di, uo, di, uo, di, uo, di, uo) is det),
|
|
in, di, uo, di, uo, di, uo, di, uo) is det.
|
|
:- mode foldr4(
|
|
in(pred(in, in, in, out, in, out, in, out, in, out) is semidet),
|
|
in, in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode foldr4(
|
|
in(pred(in, in, in, out, in, out, in, out, mdi, muo) is semidet),
|
|
in, in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldr4(
|
|
in(pred(in, in, in, out, in, out, in, out, di, uo) is semidet),
|
|
in, in, out, in, out, in, out, di, uo) is semidet.
|
|
|
|
:- pred foldr5(pred(K, V, A, A, B, B, C, C, D, D, E, E), map(K, V),
|
|
A, A, B, B, C, C, D, D, E, E).
|
|
:- mode foldr5(in(pred(in, in, in, out, in, out, in, out, in, out, in, out)
|
|
is det),
|
|
in, in, out, in, out, in, out, in, out, in, out) is det.
|
|
:- mode foldr5(in(pred(in, in, in, out, in, out, in, out, in, out, mdi, muo)
|
|
is det),
|
|
in, in, out, in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldr5(in(pred(in, in, in, out, in, out, in, out, in, out, di, uo)
|
|
is det),
|
|
in, in, out, in, out, in, out, in, out, di, uo) is det.
|
|
:- mode foldr5(in(pred(in, in, in, out, in, out, in, out, in, out, in, out)
|
|
is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode foldr5(in(pred(in, in, in, out, in, out, in, out, in, out, mdi, muo)
|
|
is semidet),
|
|
in, in, out, in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldr5(in(pred(in, in, in, out, in, out, in, out, in, out, di, uo)
|
|
is semidet),
|
|
in, in, out, in, out, in, out, in, out, di, uo) is semidet.
|
|
|
|
:- pred foldr6(pred(K, V, A, A, B, B, C, C, D, D, E, E, F, F), map(K, V),
|
|
A, A, B, B, C, C, D, D, E, E, F, F).
|
|
:- mode foldr6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, in, out) is det),
|
|
in, in, out, in, out, in, out, in, out, in, out, in, out) is det.
|
|
:- mode foldr6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, mdi, muo) is det),
|
|
in, in, out, in, out, in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode foldr6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, di, uo) is det),
|
|
in, in, out, in, out, in, out, in, out, in, out, di, uo) is det.
|
|
:- mode foldr6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, in, out) is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode foldr6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, mdi, muo) is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode foldr6(in(pred(in, in, in, out, in, out, in, out, in, out,
|
|
in, out, di, uo) is semidet),
|
|
in, in, out, in, out, in, out, in, out, in, out, di, uo) is semidet.
|
|
|
|
%---------------------%
|
|
|
|
% Apply a transformation predicate to all the values in a map.
|
|
%
|
|
:- func map_values(func(K, V) = W, map(K, V)) = map(K, W).
|
|
:- pred map_values(pred(K, V, W), map(K, V), map(K, W)).
|
|
:- mode map_values(in(pred(in, in, out) is det), in, out) is det.
|
|
:- mode map_values(in(pred(in, in, out) is semidet), in, out) is semidet.
|
|
|
|
% Same as map_values, but do not pass the key to the given predicate.
|
|
%
|
|
:- func map_values_only(func(V) = W, map(K, V)) = map(K, W).
|
|
:- pred map_values_only(pred(V, W), map(K, V), map(K, W)).
|
|
:- mode map_values_only(in(pred(in, out) is det), in, out) is det.
|
|
:- mode map_values_only(in(pred(in, out) is semidet), in, out) is semidet.
|
|
|
|
% Apply a transformation predicate to all the values in a map.
|
|
%
|
|
:- pred filter_map_values(pred(K, V, W)::in(pred(in, in, out) is semidet),
|
|
map(K, V)::in, map(K, W)::out) is det.
|
|
|
|
% Same as map_values, but do not pass the key to the given predicate.
|
|
%
|
|
:- pred filter_map_values_only(pred(V, W)::in(pred(in, out) is semidet),
|
|
map(K, V)::in, map(K, W)::out) is det.
|
|
|
|
%---------------------%
|
|
|
|
% Perform an inorder traversal by key of the map, applying a transformation
|
|
% predicate to each value while updating an accumulator.
|
|
%
|
|
:- pred map_foldl(pred(K, V, W, A, A), map(K, V), map(K, W), A, A).
|
|
:- mode map_foldl(in(pred(in, in, out, in, out) is det), in, out, in, out)
|
|
is det.
|
|
:- mode map_foldl(in(pred(in, in, out, mdi, muo) is det), in, out, mdi, muo)
|
|
is det.
|
|
:- mode map_foldl(in(pred(in, in, out, di, uo) is det), in, out, di, uo)
|
|
is det.
|
|
:- mode map_foldl(in(pred(in, in, out, in, out) is semidet), in, out,
|
|
in, out) is semidet.
|
|
:- mode map_foldl(in(pred(in, in, out, mdi, muo) is semidet), in, out,
|
|
mdi, muo) is semidet.
|
|
:- mode map_foldl(in(pred(in, in, out, di, uo) is semidet), in, out,
|
|
di, uo) is semidet.
|
|
:- mode map_foldl(in(pred(in, in, out, in, out) is cc_multi), in, out, in, out)
|
|
is cc_multi.
|
|
:- mode map_foldl(in(pred(in, in, out, mdi, muo) is cc_multi), in, out,
|
|
mdi, muo) is cc_multi.
|
|
:- mode map_foldl(in(pred(in, in, out, di, uo) is cc_multi), in, out, di, uo)
|
|
is cc_multi.
|
|
|
|
% As map_foldl, but with two accumulators.
|
|
%
|
|
:- pred map_foldl2(pred(K, V, W, A, A, B, B), map(K, V), map(K, W),
|
|
A, A, B, B).
|
|
:- mode map_foldl2(in(pred(in, in, out, in, out, in, out) is det),
|
|
in, out, in, out, in, out) is det.
|
|
:- mode map_foldl2(in(pred(in, in, out, in, out, mdi, muo) is det),
|
|
in, out, in, out, mdi, muo) is det.
|
|
:- mode map_foldl2(in(pred(in, in, out, in, out, di, uo) is det),
|
|
in, out, in, out, di, uo) is det.
|
|
:- mode map_foldl2(in(pred(in, in, out, di, uo, di, uo) is det),
|
|
in, out, di, uo, di, uo) is det.
|
|
:- mode map_foldl2(in(pred(in, in, out, in, out, in, out) is semidet),
|
|
in, out, in, out, in, out) is semidet.
|
|
:- mode map_foldl2(in(pred(in, in, out, in, out, mdi, muo) is semidet),
|
|
in, out, in, out, mdi, muo) is semidet.
|
|
:- mode map_foldl2(in(pred(in, in, out, in, out, di, uo) is semidet),
|
|
in, out, in, out, di, uo) is semidet.
|
|
:- mode map_foldl2(in(pred(in, in, out, in, out, in, out) is cc_multi),
|
|
in, out, in, out, in, out) is cc_multi.
|
|
:- mode map_foldl2(in(pred(in, in, out, in, out, mdi, muo) is cc_multi),
|
|
in, out, in, out, mdi, muo) is cc_multi.
|
|
:- mode map_foldl2(in(pred(in, in, out, in, out, di, uo) is cc_multi),
|
|
in, out, in, out, di, uo) is cc_multi.
|
|
|
|
% As map_foldl, but with three accumulators.
|
|
%
|
|
:- pred map_foldl3(pred(K, V, W, A, A, B, B, C, C), map(K, V), map(K, W),
|
|
A, A, B, B, C, C).
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, in, out, in, out, in, out) is det),
|
|
in, out, in, out, in, out, in, out) is det.
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, in, out, in, out, mdi, muo) is det),
|
|
in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, di, uo, di, uo, di, uo) is det),
|
|
in, out, di, uo, di, uo, di, uo) is det.
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, in, out, in, out, di, uo) is det),
|
|
in, out, in, out, in, out, di, uo) is det.
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, in, out, di, uo, di, uo) is det),
|
|
in, out, in, out, di, uo, di, uo) is det.
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, in, out, in, out, in, out) is semidet),
|
|
in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, in, out, in, out, mdi, muo) is semidet),
|
|
in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, in, out, in, out, di, uo) is semidet),
|
|
in, out, in, out, in, out, di, uo) is semidet.
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, in, out, in, out, in, out) is cc_multi),
|
|
in, out, in, out, in, out, in, out) is cc_multi.
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, in, out, in, out, mdi, muo) is cc_multi),
|
|
in, out, in, out, in, out, mdi, muo) is cc_multi.
|
|
:- mode map_foldl3(
|
|
in(pred(in, in, out, di, uo, di, uo, di, uo) is cc_multi),
|
|
in, out, di, uo, di, uo, di, uo) is cc_multi.
|
|
|
|
% As map_foldl, but with four accumulators.
|
|
%
|
|
:- pred map_foldl4(pred(K, V, W, A, A, B, B, C, C, D, D), map(K, V), map(K, W),
|
|
A, A, B, B, C, C, D, D).
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, in, out, in, out, in, out)
|
|
is det),
|
|
in, out, in, out, in, out, in, out, in, out) is det.
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, in, out, in, out, mdi, muo)
|
|
is det),
|
|
in, out, in, out, in, out, in, out, mdi, muo) is det.
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, di, uo, di, uo, di, uo)
|
|
is det),
|
|
in, out, in, out, di, uo, di, uo, di, uo) is det.
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, in, out, in, out, di, uo)
|
|
is det),
|
|
in, out, in, out, in, out, in, out, di, uo) is det.
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, in, out, di, uo, di, uo)
|
|
is det),
|
|
in, out, in, out, in, out, di, uo, di, uo) is det.
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, in, out, in, out, in, out)
|
|
is semidet),
|
|
in, out, in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, in, out, in, out, mdi, muo)
|
|
is semidet),
|
|
in, out, in, out, in, out, in, out, mdi, muo) is semidet.
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, in, out, in, out, di, uo)
|
|
is semidet),
|
|
in, out, in, out, in, out, in, out, di, uo) is semidet.
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, in, out, in, out, in, out)
|
|
is cc_multi),
|
|
in, out, in, out, in, out, in, out, in, out) is cc_multi.
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, in, out, in, out, mdi, muo)
|
|
is cc_multi),
|
|
in, out, in, out, in, out, in, out, mdi, muo) is cc_multi.
|
|
:- mode map_foldl4(in(pred(in, in, out, in, out, di, uo, di, uo, di, uo)
|
|
is cc_multi),
|
|
in, out, in, out, di, uo, di, uo, di, uo) is cc_multi.
|
|
|
|
%---------------------%
|
|
|
|
% As map_foldl, but without passing the key to the predicate.
|
|
% NOTE: For consistency with the naming schemes of related predicates,
|
|
% mainly map_values and map_values_only, this predicate is intended
|
|
% to change in the future by having the predicate argument
|
|
% take a key argument.
|
|
%
|
|
:- pred map_values_foldl(pred(V, W, A, A), map(K, V), map(K, W), A, A).
|
|
:- mode map_values_foldl(in(pred(in, out, in, out) is det),
|
|
in, out, in, out) is det.
|
|
:- mode map_values_foldl(in(pred(in, out, di, uo) is det),
|
|
in, out, di, uo) is det.
|
|
:- mode map_values_foldl(in(pred(in, out, in, out) is semidet),
|
|
in, out, in, out) is semidet.
|
|
:- mode map_values_foldl(in(pred(in, out, in, out) is cc_multi),
|
|
in, out, in, out) is cc_multi.
|
|
:- mode map_values_foldl(in(pred(in, out, di, uo) is cc_multi),
|
|
in, out, di, uo) is cc_multi.
|
|
|
|
% As map_foldl, but without passing the key to the predicate.
|
|
%
|
|
:- pred map_values_only_foldl(pred(V, W, A, A), map(K, V), map(K, W), A, A).
|
|
:- mode map_values_only_foldl(in(pred(in, out, in, out) is det),
|
|
in, out, in, out) is det.
|
|
:- mode map_values_only_foldl(in(pred(in, out, di, uo) is det),
|
|
in, out, di, uo) is det.
|
|
:- mode map_values_only_foldl(in(pred(in, out, in, out) is semidet),
|
|
in, out, in, out) is semidet.
|
|
:- mode map_values_only_foldl(in(pred(in, out, in, out) is cc_multi),
|
|
in, out, in, out) is cc_multi.
|
|
:- mode map_values_only_foldl(in(pred(in, out, di, uo) is cc_multi),
|
|
in, out, di, uo) is cc_multi.
|
|
|
|
% As map_values_only_foldl, but with two accumulators.
|
|
%
|
|
:- pred map_values_foldl2(pred(V, W, A, A, B, B), map(K, V), map(K, W),
|
|
A, A, B, B).
|
|
:- mode map_values_foldl2(in(pred(in, out, in, out, in, out) is det),
|
|
in, out, in, out, in, out) is det.
|
|
:- mode map_values_foldl2(in(pred(in, out, in, out, di, uo) is det),
|
|
in, out, in, out, di, uo) is det.
|
|
:- mode map_values_foldl2(in(pred(in, out, di, uo, di, uo) is det),
|
|
in, out, di, uo, di, uo) is det.
|
|
:- mode map_values_foldl2(in(pred(in, out, in, out, in, out) is semidet),
|
|
in, out, in, out, in, out) is semidet.
|
|
:- mode map_values_foldl2(in(pred(in, out, in, out, in, out) is cc_multi),
|
|
in, out, in, out, in, out) is cc_multi.
|
|
:- mode map_values_foldl2(in(pred(in, out, in, out, di, uo) is cc_multi),
|
|
in, out, in, out, di, uo) is cc_multi.
|
|
|
|
% As map_values_only_foldl, but with two accumulators.
|
|
%
|
|
:- pred map_values_only_foldl2(pred(V, W, A, A, B, B), map(K, V), map(K, W),
|
|
A, A, B, B).
|
|
:- mode map_values_only_foldl2(in(pred(in, out, in, out, in, out) is det),
|
|
in, out, in, out, in, out) is det.
|
|
:- mode map_values_only_foldl2(in(pred(in, out, in, out, di, uo) is det),
|
|
in, out, in, out, di, uo) is det.
|
|
:- mode map_values_only_foldl2(in(pred(in, out, di, uo, di, uo) is det),
|
|
in, out, di, uo, di, uo) is det.
|
|
:- mode map_values_only_foldl2(in(pred(in, out, in, out, in, out) is semidet),
|
|
in, out, in, out, in, out) is semidet.
|
|
:- mode map_values_only_foldl2(in(pred(in, out, in, out, in, out) is cc_multi),
|
|
in, out, in, out, in, out) is cc_multi.
|
|
:- mode map_values_only_foldl2(in(pred(in, out, in, out, di, uo) is cc_multi),
|
|
in, out, in, out, di, uo) is cc_multi.
|
|
|
|
% As map_values_only_foldl, but with three accumulators.
|
|
%
|
|
:- pred map_values_foldl3(pred(V, W, A, A, B, B, C, C),
|
|
map(K, V), map(K, W), A, A, B, B, C, C).
|
|
:- mode map_values_foldl3(
|
|
in(pred(in, out, in, out, in, out, in, out) is det),
|
|
in, out, in, out, in, out, in, out) is det.
|
|
:- mode map_values_foldl3(
|
|
in(pred(in, out, in, out, in, out, di, uo) is det),
|
|
in, out, in, out, in, out, di, uo) is det.
|
|
:- mode map_values_foldl3(
|
|
in(pred(in, out, di, uo, di, uo, di, uo) is det),
|
|
in, out, di, uo, di, uo, di, uo) is det.
|
|
:- mode map_values_foldl3(
|
|
in(pred(in, out, in, out, di, uo, di, uo) is det),
|
|
in, out, in, out, di, uo, di, uo) is det.
|
|
:- mode map_values_foldl3(
|
|
in(pred(in, out, in, out, in, out, in, out) is semidet),
|
|
in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode map_values_foldl3(
|
|
in(pred(in, out, in, out, in, out, in, out) is cc_multi),
|
|
in, out, in, out, in, out, in, out) is cc_multi.
|
|
:- mode map_values_foldl3(
|
|
in(pred(in, out, in, out, in, out, di, uo) is cc_multi),
|
|
in, out, in, out, in, out, di, uo) is cc_multi.
|
|
|
|
% As map_values_only_foldl, but with three accumulators.
|
|
%
|
|
:- pred map_values_only_foldl3(pred(V, W, A, A, B, B, C, C),
|
|
map(K, V), map(K, W), A, A, B, B, C, C).
|
|
:- mode map_values_only_foldl3(
|
|
in(pred(in, out, in, out, in, out, in, out) is det),
|
|
in, out, in, out, in, out, in, out) is det.
|
|
:- mode map_values_only_foldl3(
|
|
in(pred(in, out, in, out, in, out, di, uo) is det),
|
|
in, out, in, out, in, out, di, uo) is det.
|
|
:- mode map_values_only_foldl3(
|
|
in(pred(in, out, in, out, di, uo, di, uo) is det),
|
|
in, out, in, out, di, uo, di, uo) is det.
|
|
:- mode map_values_only_foldl3(
|
|
in(pred(in, out, di, uo, di, uo, di, uo) is det),
|
|
in, out, di, uo, di, uo, di, uo) is det.
|
|
:- mode map_values_only_foldl3(
|
|
in(pred(in, out, in, out, in, out, in, out) is semidet),
|
|
in, out, in, out, in, out, in, out) is semidet.
|
|
:- mode map_values_only_foldl3(
|
|
in(pred(in, out, in, out, in, out, in, out) is cc_multi),
|
|
in, out, in, out, in, out, in, out) is cc_multi.
|
|
:- mode map_values_only_foldl3(
|
|
in(pred(in, out, in, out, in, out, di, uo) is cc_multi),
|
|
in, out, in, out, in, out, di, uo) is cc_multi.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
% Everything below here is not intended to be part of the public interface,
|
|
% and will not be included in the Mercury library reference manual.
|
|
|
|
:- interface.
|
|
|
|
:- import_module term. % for var/1.
|
|
:- import_module tree234.
|
|
|
|
:- type map(K, V) == tree234(K, V).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Note to implementors:
|
|
%
|
|
% This is the old version of map.merge/3. It is buggy in the sense that if the
|
|
% sets of keys of the input maps are not disjoint, it won't throw an exception,
|
|
% but will insert the key and the larger of the two corresponding values into
|
|
% the output map. (Actually, it inserts the key into the output map twice,
|
|
% once with each value, but it inserts the key with the smaller corresponding
|
|
% value first, and this is overwritten by the larger corresponding value
|
|
% on the next insert.)
|
|
%
|
|
% Eventually we would like to get rid of this version, but some of the code
|
|
% in the compiler currently assumes this behaviour, and fixing this
|
|
% is non-trivial.
|
|
|
|
:- func old_merge(map(K, V), map(K, V)) = map(K, V).
|
|
:- pred old_merge(map(K, V)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pragma type_spec(pred(map.search/3), K = var(_)).
|
|
:- pragma type_spec(pred(map.search/3), K = int).
|
|
|
|
:- pragma type_spec(func(map.search/2), K = var(_)).
|
|
:- pragma type_spec(func(map.search/2), K = int).
|
|
|
|
:- pragma type_spec(pred(map.lookup/3), K = var(_)).
|
|
:- pragma type_spec(pred(map.lookup/3), K = int).
|
|
|
|
:- pragma type_spec(func(map.lookup/2), K = var(_)).
|
|
:- pragma type_spec(func(map.lookup/2), K = int).
|
|
|
|
:- pragma type_spec(map.insert(in, in, in, out), K = var(_)).
|
|
:- pragma type_spec(map.insert(in, in, in, out), K = int).
|
|
|
|
:- pragma type_spec(map.det_insert(in, in, in, out), K = var(_)).
|
|
:- pragma type_spec(map.det_insert(in, in, in, out), K = int).
|
|
|
|
:- pragma type_spec(map.set(in, in, in, out), K = var(_)).
|
|
:- pragma type_spec(map.set(in, in, in, out), K = int).
|
|
|
|
:- pragma type_spec(map.update(in, in, in, out), K = var(_)).
|
|
:- pragma type_spec(map.update(in, in, in, out), K = int).
|
|
|
|
:- pragma type_spec(pred(map.det_update/4), K = var(_)).
|
|
:- pragma type_spec(pred(map.det_update/4), K = int).
|
|
|
|
:- pragma type_spec(pred(map.search_insert/5), K = var(_)).
|
|
:- pragma type_spec(pred(map.search_insert/5), K = int).
|
|
|
|
:- pragma type_spec(func(map.overlay/2), K = var(_)).
|
|
:- pragma type_spec(pred(map.overlay/3), K = var(_)).
|
|
|
|
:- pragma type_spec(func(map.select/2), K = var(_)).
|
|
:- pragma type_spec(pred(map.select/3), K = var(_)).
|
|
|
|
:- pragma type_spec(func(map.select_sorted_list/2), K = var(_)).
|
|
:- pragma type_spec(pred(map.select_sorted_list/3), K = var(_)).
|
|
|
|
:- pragma type_spec(func(map.elem/2), K = int).
|
|
:- pragma type_spec(func(map.elem/2), K = var(_)).
|
|
|
|
:- pragma type_spec(func(map.det_elem/2), K = int).
|
|
:- pragma type_spec(func(map.det_elem/2), K = var(_)).
|
|
|
|
:- pragma type_spec(func('elem :='/3), K = int).
|
|
:- pragma type_spec(func('elem :='/3), K = var(_)).
|
|
|
|
:- pragma type_spec(func('det_elem :='/3), K = int).
|
|
:- pragma type_spec(func('det_elem :='/3), K = var(_)).
|
|
|
|
:- implementation.
|
|
|
|
:- import_module int.
|
|
:- import_module pair.
|
|
:- import_module require.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
init = M :-
|
|
map.init(M).
|
|
|
|
init(M) :-
|
|
tree234.init(M).
|
|
|
|
singleton(K, V) =
|
|
tree234.singleton(K, V).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
is_empty(M) :-
|
|
tree234.is_empty(M).
|
|
|
|
is_non_empty(M) :-
|
|
tree234.is_non_empty(M).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
contains(Map, K) :-
|
|
map.search(Map, K, _).
|
|
|
|
search(M, K) = V :-
|
|
map.search(M, K, V).
|
|
|
|
search(Map, K, V) :-
|
|
tree234.search(Map, K, V).
|
|
|
|
lookup(M, K) = V :-
|
|
map.lookup(M, K, V).
|
|
|
|
lookup(Map, K, V) :-
|
|
( if tree234.search(Map, K, VPrime) then
|
|
V = VPrime
|
|
else
|
|
report_lookup_error("map.lookup: key not found", K, V)
|
|
).
|
|
|
|
inverse_search(Map, V, K) :-
|
|
map.member(Map, K, V).
|
|
|
|
lower_bound_search(Map, SearchK, K, V) :-
|
|
tree234.lower_bound_search(Map, SearchK, K, V).
|
|
|
|
lower_bound_lookup(Map, SearchK, K, V) :-
|
|
( if tree234.lower_bound_search(Map, SearchK, KPrime, VPrime) then
|
|
K = KPrime,
|
|
V = VPrime
|
|
else
|
|
report_lookup_error("map.lower_bound_lookup: key not found",
|
|
SearchK, V)
|
|
).
|
|
|
|
upper_bound_search(Map, SearchK, K, V) :-
|
|
tree234.upper_bound_search(Map, SearchK, K, V).
|
|
|
|
upper_bound_lookup(Map, SearchK, K, V) :-
|
|
( if tree234.upper_bound_search(Map, SearchK, KPrime, VPrime) then
|
|
K = KPrime,
|
|
V = VPrime
|
|
else
|
|
report_lookup_error("map.upper_bound_lookup: key not found",
|
|
SearchK, V)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
max_key(Map) = Key :-
|
|
map.max_key(Map, Key).
|
|
|
|
max_key(Map, Key) :-
|
|
tree234.max_key(Map, Key).
|
|
|
|
det_max_key(Map) =
|
|
( if map.max_key(Map, Key) then
|
|
Key
|
|
else
|
|
unexpected($pred, "map.max_key failed")
|
|
).
|
|
|
|
min_key(Map) = Key :-
|
|
map.min_key(Map, Key).
|
|
|
|
min_key(Map, Key) :-
|
|
tree234.min_key(Map, Key).
|
|
|
|
det_min_key(Map) =
|
|
( if map.min_key(Map, Key) then
|
|
Key
|
|
else
|
|
unexpected($pred, "map.min_key failed")
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
insert(M0, K, V) = M :-
|
|
map.insert(K, V, M0, M).
|
|
|
|
insert(K, V, !Map) :-
|
|
tree234.insert(K, V, !Map).
|
|
|
|
det_insert(M0, K, V) = M :-
|
|
map.det_insert(K, V, M0, M).
|
|
|
|
det_insert(K, V, !Map) :-
|
|
( if tree234.insert(K, V, !.Map, NewMap) then
|
|
!:Map = NewMap
|
|
else
|
|
report_lookup_error("map.det_insert: key already present", K, V)
|
|
).
|
|
|
|
det_insert_from_corresponding_lists(M0, Ks, Vs) = M :-
|
|
map.det_insert_from_corresponding_lists(Ks, Vs, M0, M).
|
|
|
|
det_insert_from_corresponding_lists([], [], !Map).
|
|
det_insert_from_corresponding_lists([], [_ | _], _, _) :-
|
|
unexpected($pred, "list length mismatch").
|
|
det_insert_from_corresponding_lists([_ | _], [], _, _) :-
|
|
unexpected($pred, "list length mismatch").
|
|
det_insert_from_corresponding_lists([K | Ks], [V | Vs], !Map) :-
|
|
map.det_insert(K, V, !Map),
|
|
map.det_insert_from_corresponding_lists(Ks, Vs, !Map).
|
|
|
|
det_insert_from_assoc_list(M0, AL) = M :-
|
|
map.det_insert_from_assoc_list(AL, M0, M).
|
|
|
|
det_insert_from_assoc_list([], !Map).
|
|
det_insert_from_assoc_list([K - V | KVs], !Map) :-
|
|
map.det_insert(K, V, !Map),
|
|
map.det_insert_from_assoc_list(KVs, !Map).
|
|
|
|
%---------------------%
|
|
|
|
search_insert(K, V, MaybeOldV, !Map) :-
|
|
tree234.search_insert(K, V, MaybeOldV, !Map).
|
|
|
|
%---------------------%
|
|
|
|
update(M0, K, V) = M :-
|
|
map.update(K, V, M0, M).
|
|
|
|
update(K, V, !Map) :-
|
|
tree234.update(K, V, !Map).
|
|
|
|
det_update(M0, K, V) = M :-
|
|
map.det_update(K, V, M0, M).
|
|
|
|
det_update(K, V, !Map) :-
|
|
( if tree234.update(K, V, !.Map, NewMap) then
|
|
!:Map = NewMap
|
|
else
|
|
report_lookup_error("map.det_update: key not found", K, V)
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
set(M0, K, V) = M :-
|
|
map.set(K, V, M0, M).
|
|
|
|
set(K, V, !Map) :-
|
|
tree234.set(K, V, !Map).
|
|
|
|
set_from_corresponding_lists(M0, Ks, Vs) = M :-
|
|
map.set_from_corresponding_lists(Ks, Vs, M0, M).
|
|
|
|
set_from_corresponding_lists([], [], !Map).
|
|
set_from_corresponding_lists([], [_ | _], _, _) :-
|
|
unexpected($pred, "list length mismatch").
|
|
set_from_corresponding_lists([_ | _], [], _, _) :-
|
|
unexpected($pred, "list length mismatch").
|
|
set_from_corresponding_lists([K | Ks], [V | Vs], !Map) :-
|
|
map.set(K, V, !Map),
|
|
map.set_from_corresponding_lists(Ks, Vs, !Map).
|
|
|
|
set_from_assoc_list(M0, AL) = M :-
|
|
map.set_from_assoc_list(AL, M0, M).
|
|
|
|
set_from_assoc_list([], !Map).
|
|
set_from_assoc_list([K - V | KVs], !Map) :-
|
|
map.set(K, V, !Map),
|
|
map.set_from_assoc_list(KVs, !Map).
|
|
|
|
%---------------------%
|
|
|
|
delete(M0, K) = M :-
|
|
map.delete(K, M0, M).
|
|
|
|
delete(Key, !Map) :-
|
|
tree234.delete(Key, !Map).
|
|
|
|
delete_list(M0, Ks) = M :-
|
|
map.delete_list(Ks, M0, M).
|
|
|
|
delete_list([], !Map).
|
|
delete_list([DeleteKey | DeleteKeys], !Map) :-
|
|
map.delete(DeleteKey, !Map),
|
|
map.delete_list(DeleteKeys, !Map).
|
|
|
|
delete_sorted_list(M0, Ks) = M :-
|
|
map.delete_sorted_list(Ks, M0, M).
|
|
|
|
delete_sorted_list(DeleteKeys, !Map) :-
|
|
list.length(DeleteKeys, NumDeleteKeys),
|
|
find_min_size_based_on_depth(!.Map, MinSize),
|
|
( if NumDeleteKeys * 5 < MinSize then
|
|
% Use this technique when we delete fewer than 20% of the keys.
|
|
map.delete_list(DeleteKeys, !Map)
|
|
else
|
|
% Use this technique when we delete at least 20% of the keys.
|
|
map.to_assoc_list(!.Map, Pairs0),
|
|
map.delete_sorted_list_loop(DeleteKeys, Pairs0, [], RevPairs,
|
|
LeftOverPairs),
|
|
reverse_list_acc(RevPairs, LeftOverPairs, Pairs),
|
|
% Pairs = list.reverse(RevPairs) ++ LeftOverPairs,
|
|
map.from_assoc_list(Pairs, !:Map)
|
|
).
|
|
|
|
:- pred delete_sorted_list_loop(list(K)::in,
|
|
assoc_list(K, V)::in, assoc_list(K, V)::in, assoc_list(K, V)::out,
|
|
assoc_list(K, V)::out) is det.
|
|
|
|
delete_sorted_list_loop([], Pairs, !RevPairs, Pairs).
|
|
delete_sorted_list_loop([_ | _], [], !RevPairs, []).
|
|
delete_sorted_list_loop([DeleteKey | DeleteKeys], [Pair0 | Pairs0],
|
|
!RevPairs, LeftOverPairs) :-
|
|
Pair0 = Key0 - _,
|
|
compare(Result, DeleteKey, Key0),
|
|
(
|
|
Result = (<),
|
|
map.delete_sorted_list_loop(DeleteKeys, [Pair0 | Pairs0],
|
|
!RevPairs, LeftOverPairs)
|
|
;
|
|
Result = (=),
|
|
map.delete_sorted_list_loop(DeleteKeys, Pairs0,
|
|
!RevPairs, LeftOverPairs)
|
|
;
|
|
Result = (>),
|
|
!:RevPairs = [Pair0 | !.RevPairs],
|
|
map.delete_sorted_list_loop([DeleteKey | DeleteKeys], Pairs0,
|
|
!RevPairs, LeftOverPairs)
|
|
).
|
|
|
|
:- pred reverse_list_acc(list(T)::in, list(T)::in, list(T)::out) is det.
|
|
|
|
reverse_list_acc([], L, L).
|
|
reverse_list_acc([X | Xs], L0, L) :-
|
|
reverse_list_acc(Xs, [X | L0], L).
|
|
|
|
%---------------------%
|
|
|
|
remove(Key, Value, !Map) :-
|
|
tree234.remove(Key, Value, !Map).
|
|
|
|
det_remove(Key, Value, !Map) :-
|
|
( if tree234.remove(Key, ValuePrime, !.Map, MapPrime) then
|
|
Value = ValuePrime,
|
|
!:Map = MapPrime
|
|
else
|
|
report_lookup_error("map.det_remove: key not found", Key, Value)
|
|
).
|
|
|
|
remove_smallest(K, V, !Map) :-
|
|
tree234.remove_smallest(K, V, !Map).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
elem(Key, Map) = map.search(Map, Key).
|
|
|
|
det_elem(Key, Map) = map.lookup(Map, Key).
|
|
|
|
'elem :='(Key, Map, Value) = map.set(Map, Key, Value).
|
|
|
|
'det_elem :='(Key, Map, Value) = map.det_update(Map, Key, Value).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
member(Map, K, V) :-
|
|
tree234.member(Map, K, V).
|
|
|
|
keys(Map) = Keys :-
|
|
map.keys(Map, Keys).
|
|
|
|
keys(Map, Keys) :-
|
|
tree234.keys(Map, Keys).
|
|
|
|
sorted_keys(Map) = Keys :-
|
|
map.sorted_keys(Map, Keys).
|
|
|
|
sorted_keys(Map, Keys) :-
|
|
% Guaranteed to yield sorted lists.
|
|
tree234.keys(Map, Keys).
|
|
|
|
keys_as_set(Map) = KeySet :-
|
|
keys_as_set(Map, KeySet).
|
|
|
|
keys_as_set(Map, KeySet) :-
|
|
map.sorted_keys(Map, Keys),
|
|
set.sorted_list_to_set(Keys, KeySet).
|
|
|
|
values(M) = Vs :-
|
|
map.values(M, Vs).
|
|
|
|
values(Map, KeyList) :-
|
|
tree234.values(Map, KeyList).
|
|
|
|
keys_and_values(Map, KeyList, ValueList) :-
|
|
tree234.keys_and_values(Map, KeyList, ValueList).
|
|
|
|
sorted_keys_match(Map, List) :-
|
|
tree234.sorted_keys_match(Map, List).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
transform_value(P, K, !Map) :-
|
|
tree234.transform_value(P, K, !Map).
|
|
|
|
det_transform_value(F, K, !.Map) = !:Map :-
|
|
map.det_transform_value(pred(V0::in, V::out) is det :- V = F(V0), K,
|
|
!Map).
|
|
|
|
det_transform_value(P, K, !Map) :-
|
|
( if map.transform_value(P, K, !.Map, NewMap) then
|
|
!:Map = NewMap
|
|
else
|
|
report_lookup_error("map.det_transform_value: key not found", K)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
from_assoc_list(AL) = M :-
|
|
map.from_assoc_list(AL, M).
|
|
|
|
from_assoc_list(L, M) :-
|
|
tree234.assoc_list_to_tree234(L, M).
|
|
|
|
from_sorted_assoc_list(AL) = M :-
|
|
map.from_sorted_assoc_list(AL, M).
|
|
|
|
from_sorted_assoc_list(L, M) :-
|
|
tree234.from_sorted_assoc_list(L, M).
|
|
|
|
from_rev_sorted_assoc_list(AL) = M :-
|
|
map.from_rev_sorted_assoc_list(AL, M).
|
|
|
|
from_rev_sorted_assoc_list(L, M) :-
|
|
tree234.from_rev_sorted_assoc_list(L, M).
|
|
|
|
from_corresponding_lists(Ks, Vs) = M :-
|
|
map.from_corresponding_lists(Ks, Vs, M).
|
|
|
|
from_corresponding_lists(Keys, Values, Map) :-
|
|
assoc_list.from_corresponding_lists(Keys, Values, AssocList),
|
|
tree234.assoc_list_to_tree234(AssocList, Map).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
to_assoc_list(M) = AL :-
|
|
map.to_assoc_list(M, AL).
|
|
|
|
to_assoc_list(M, L) :-
|
|
tree234.tree234_to_assoc_list(M, L).
|
|
|
|
to_sorted_assoc_list(M) = AL :-
|
|
map.to_sorted_assoc_list(M, AL).
|
|
|
|
to_sorted_assoc_list(M, L) :-
|
|
% Guaranteed to yield sorted lists.
|
|
tree234.tree234_to_assoc_list(M, L).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
reverse_map(Map) = RevMap :-
|
|
map.foldl(map.reverse_map_2, Map, map.init, RevMap).
|
|
|
|
:- pred reverse_map_2(K::in, V::in,
|
|
map(V, set(K))::in, map(V, set(K))::out) is det.
|
|
|
|
reverse_map_2(Key, Value, !RevMap) :-
|
|
( if map.search(!.RevMap, Value, Keys0) then
|
|
set.insert(Key, Keys0, Keys),
|
|
map.det_update(Value, Keys, !RevMap)
|
|
else
|
|
map.det_insert(Value, set.make_singleton_set(Key), !RevMap)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
select(FullMap, KeySet) = SelectMap :-
|
|
map.select(FullMap, KeySet, SelectMap).
|
|
|
|
select(FullMap, KeySet, SelectMap) :-
|
|
set.to_sorted_list(KeySet, Keys),
|
|
select_sorted_list(FullMap, Keys, SelectMap).
|
|
|
|
select_sorted_list(FullMap, Keys) = SelectMap :-
|
|
map.select_sorted_list(FullMap, Keys, SelectMap).
|
|
|
|
select_sorted_list(FullMap, Keys, SelectMap) :-
|
|
map.select_loop(Keys, FullMap, [], RevSelectAL),
|
|
map.from_rev_sorted_assoc_list(RevSelectAL, SelectMap).
|
|
|
|
:- pred select_loop(list(K)::in, map(K, V)::in,
|
|
assoc_list(K, V)::in, assoc_list(K, V)::out) is det.
|
|
:- pragma type_spec(pred(map.select_loop/4), K = var(_)).
|
|
|
|
select_loop([], _FullMap, !RevSelectAL).
|
|
select_loop([K | Ks], FullMap, !RevSelectAL) :-
|
|
( if map.search(FullMap, K, V) then
|
|
!:RevSelectAL = [K - V | !.RevSelectAL]
|
|
else
|
|
true
|
|
),
|
|
map.select_loop(Ks, FullMap, !RevSelectAL).
|
|
|
|
%---------------------%
|
|
|
|
select_unselect(FullMap, KeySet, SelectMap, UnselectMap) :-
|
|
set.to_sorted_list(KeySet, Keys),
|
|
select_unselect_sorted_list(FullMap, Keys, SelectMap, UnselectMap).
|
|
|
|
select_unselect_sorted_list(FullMap, Keys, SelectMap, UnselectMap) :-
|
|
map.to_assoc_list(FullMap, FullAL),
|
|
map.select_unselect_loop(FullAL, Keys, [], RevSelectAL, [], RevUnselectAL),
|
|
map.from_rev_sorted_assoc_list(RevSelectAL, SelectMap),
|
|
map.from_rev_sorted_assoc_list(RevUnselectAL, UnselectMap).
|
|
|
|
:- pred select_unselect_loop(assoc_list(K, V)::in, list(K)::in,
|
|
assoc_list(K, V)::in, assoc_list(K, V)::out,
|
|
assoc_list(K, V)::in, assoc_list(K, V)::out) is det.
|
|
|
|
select_unselect_loop([], _, !RevSelectAL, !RevUnselectAL).
|
|
select_unselect_loop(FullAL @ [FullK - FullV | TailFullAL], KeysAL,
|
|
!RevSelectAL, !RevUnselectAL) :-
|
|
(
|
|
KeysAL = [],
|
|
% There are no keys left in the key set.
|
|
% Move FullK - FullV (and every pair after them) to the unselect list.
|
|
NextFullAL = TailFullAL,
|
|
NextKeysAL = KeysAL,
|
|
!:RevUnselectAL = [FullK - FullV | !.RevUnselectAL]
|
|
;
|
|
KeysAL = [KeyK | TailKeysAL],
|
|
compare(Result, KeyK, FullK),
|
|
(
|
|
Result = (<),
|
|
% KeyK does not occur in the full map. Consume it.
|
|
NextFullAL = FullAL,
|
|
NextKeysAL = TailKeysAL
|
|
;
|
|
Result = (=),
|
|
% KeyK does occur in the full map. Consume both it
|
|
% and the matching FullK - FullV pair, and move the pair
|
|
% to the select list.
|
|
NextFullAL = TailFullAL,
|
|
NextKeysAL = TailKeysAL,
|
|
!:RevSelectAL = [FullK - FullV | !.RevSelectAL]
|
|
;
|
|
Result = (>),
|
|
% We don't yet know whether KeyK occurs in the full map,
|
|
% but we know that FullK is not in the key set.
|
|
% Move the FullK - FullV pair to the unselect list.
|
|
NextFullAL = TailFullAL,
|
|
NextKeysAL = KeysAL,
|
|
!:RevUnselectAL = [FullK - FullV | !.RevUnselectAL]
|
|
)
|
|
),
|
|
map.select_unselect_loop(NextFullAL, NextKeysAL,
|
|
!RevSelectAL, !RevUnselectAL).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
apply_to_list(Ks, M) = Vs :-
|
|
map.apply_to_list(Ks, M, Vs).
|
|
|
|
apply_to_list([], _, []).
|
|
apply_to_list([K | Ks], Map, [V | Vs]) :-
|
|
map.lookup(Map, K, V),
|
|
map.apply_to_list(Ks, Map, Vs).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
merge(MapA, MapB) = MergedMap :-
|
|
map.merge(MapA, MapB, MergedMap).
|
|
|
|
merge(MapA, MapB, MergedMap) :-
|
|
% You may wish to compare this to old_merge below.
|
|
map.to_assoc_list(MapB, MapBList),
|
|
map.det_insert_from_assoc_list(MapBList, MapA, MergedMap).
|
|
|
|
overlay(MapA, MapB) = OverlayMap :-
|
|
map.overlay(MapA, MapB, OverlayMap).
|
|
|
|
overlay(MapA, MapB, OverlayMap) :-
|
|
map.to_assoc_list(MapB, AssocListB),
|
|
map.overlay_2(AssocListB, MapA, OverlayMap).
|
|
|
|
:- pred overlay_2(assoc_list(K, V)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
:- pragma type_spec(pred(map.overlay_2/3), K = var(_)).
|
|
|
|
overlay_2([], !Map).
|
|
overlay_2([K - V | AssocList], !Map) :-
|
|
map.set(K, V, !Map),
|
|
map.overlay_2(AssocList, !Map).
|
|
|
|
overlay_large_map(MapA, MapB) = OverlayMap :-
|
|
map.overlay_large_map(MapA, MapB, OverlayMap).
|
|
|
|
overlay_large_map(MapA, MapB, OverlayMap) :-
|
|
map.to_assoc_list(MapA, AssocListA),
|
|
map.overlay_large_map_2(AssocListA, MapB, OverlayMap).
|
|
|
|
:- pred overlay_large_map_2(assoc_list(K, V)::in,
|
|
map(K, V)::in, map(K, V)::out) is det.
|
|
:- pragma type_spec(pred(map.overlay_large_map_2/3), K = var(_)).
|
|
|
|
overlay_large_map_2([], Map, Map).
|
|
overlay_large_map_2([K - V | AssocList], Map0, Map) :-
|
|
( if map.insert(K, V, Map0, Map1) then
|
|
Map2 = Map1
|
|
else
|
|
Map2 = Map0
|
|
),
|
|
map.overlay_large_map_2(AssocList, Map2, Map).
|
|
|
|
%---------------------%
|
|
|
|
common_subset(MapA, MapB) = CommonMap :-
|
|
map.to_sorted_assoc_list(MapA, AssocListA),
|
|
map.to_sorted_assoc_list(MapB, AssocListB),
|
|
map.common_subset_loop(AssocListA, AssocListB, [], RevCommonAssocList),
|
|
map.from_rev_sorted_assoc_list(RevCommonAssocList, CommonMap).
|
|
|
|
:- pred common_subset_loop(assoc_list(K, V)::in, assoc_list(K, V)::in,
|
|
assoc_list(K, V)::in, assoc_list(K, V)::out) is det.
|
|
|
|
common_subset_loop(ListA, ListB, !RevCommonList) :-
|
|
(
|
|
ListA = [],
|
|
ListB = []
|
|
;
|
|
ListA = [_ | _],
|
|
ListB = []
|
|
;
|
|
ListA = [],
|
|
ListB = [_ | _]
|
|
;
|
|
ListA = [KeyA - ValueA | TailA],
|
|
ListB = [KeyB - ValueB | TailB],
|
|
compare(R, KeyA, KeyB),
|
|
(
|
|
R = (=),
|
|
( if ValueA = ValueB then
|
|
!:RevCommonList = [KeyA - ValueA | !.RevCommonList]
|
|
else
|
|
true
|
|
),
|
|
map.common_subset_loop(TailA, TailB, !RevCommonList)
|
|
;
|
|
R = (<),
|
|
% KeyA has no match in ListB.
|
|
map.common_subset_loop(TailA, ListB, !RevCommonList)
|
|
;
|
|
R = (>),
|
|
% KeyB has no match in ListA.
|
|
map.common_subset_loop(ListA, TailB, !RevCommonList)
|
|
)
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
intersect(F, MapA, MapB) = IntersectMap :-
|
|
P = (pred(X::in, Y::in, Z::out) is det :- Z = F(X, Y) ),
|
|
map.intersect(P, MapA, MapB, IntersectMap).
|
|
|
|
intersect(CommonPred, MapA, MapB, Common) :-
|
|
map.to_sorted_assoc_list(MapA, AssocListA),
|
|
map.to_sorted_assoc_list(MapB, AssocListB),
|
|
map.intersect_loop(AssocListA, AssocListB, CommonPred,
|
|
[], RevCommonAssocList),
|
|
map.from_rev_sorted_assoc_list(RevCommonAssocList, Common).
|
|
|
|
:- pred intersect_loop(assoc_list(K, V), assoc_list(K, V), pred(V, V, V),
|
|
assoc_list(K, V), assoc_list(K, V)).
|
|
:- mode intersect_loop(in, in, in(pred(in, in, out) is semidet), in, out)
|
|
is semidet.
|
|
:- mode intersect_loop(in, in, in(pred(in, in, out) is det), in, out)
|
|
is det.
|
|
|
|
intersect_loop(ListA, ListB, CommonPred, !RevCommonList) :-
|
|
(
|
|
ListA = [],
|
|
ListB = []
|
|
;
|
|
ListA = [_ | _],
|
|
ListB = []
|
|
;
|
|
ListA = [],
|
|
ListB = [_ | _]
|
|
;
|
|
ListA = [KeyA - ValueA | TailA],
|
|
ListB = [KeyB - ValueB | TailB],
|
|
compare(R, KeyA, KeyB),
|
|
(
|
|
R = (=),
|
|
CommonPred(ValueA, ValueB, Value),
|
|
!:RevCommonList = [KeyA - Value | !.RevCommonList],
|
|
map.intersect_loop(TailA, TailB, CommonPred,
|
|
!RevCommonList)
|
|
;
|
|
R = (<),
|
|
map.intersect_loop(TailA, ListB, CommonPred, !RevCommonList)
|
|
;
|
|
R = (>),
|
|
map.intersect_loop(ListA, TailB, CommonPred, !RevCommonList)
|
|
)
|
|
).
|
|
|
|
det_intersect(PF, MapA, MapB) = IntersectMap :-
|
|
P = (pred(X::in, Y::in, Z::out) is semidet :- Z = PF(X, Y) ),
|
|
map.det_intersect(P, MapA, MapB, IntersectMap).
|
|
|
|
det_intersect(CommonPred, MapA, MapB, CommonMap) :-
|
|
( if map.intersect(CommonPred, MapA, MapB, CommonMapPrime) then
|
|
CommonMap = CommonMapPrime
|
|
else
|
|
unexpected($pred, "map.intersect failed")
|
|
).
|
|
|
|
intersect_list(CommonPred, HeadMap, TailMaps, Common) :-
|
|
map.to_sorted_assoc_list(HeadMap, HeadAssocList),
|
|
list.map(map.to_sorted_assoc_list, TailMaps, TailAssocLists),
|
|
map.intersect_list_passes(HeadAssocList, TailAssocLists, CommonPred,
|
|
CommonAssocList),
|
|
map.from_sorted_assoc_list(CommonAssocList, Common).
|
|
|
|
:- pred intersect_list_passes(assoc_list(K, V), list(assoc_list(K, V)),
|
|
pred(V, V, V), assoc_list(K, V)).
|
|
:- mode intersect_list_passes(in, in, in(pred(in, in, out) is semidet), out)
|
|
is semidet.
|
|
:- mode intersect_list_passes(in, in, in(pred(in, in, out) is det), out)
|
|
is det.
|
|
|
|
intersect_list_passes(HeadAssocList, TailAssocLists, CommonPred,
|
|
CommonAssocList) :-
|
|
(
|
|
TailAssocLists = [],
|
|
CommonAssocList = HeadAssocList
|
|
;
|
|
TailAssocLists = [_ | _],
|
|
map.intersect_list_pass(HeadAssocList, TailAssocLists, CommonPred,
|
|
FirstAssocList, LaterAssocLists),
|
|
map.intersect_list_passes(FirstAssocList, LaterAssocLists, CommonPred,
|
|
CommonAssocList)
|
|
).
|
|
|
|
% If the list [HeadAssocList | TailAssocLists] has 2k sorted association
|
|
% lists (representing 2k maps), then reduce these to k sorted association
|
|
% lists by intersecting assoc list 2i with assoc list 2i+1 for all i
|
|
% in 0..(k-1). If it has 2k+1 sorted association lists, intersect
|
|
% the first 2k as above, and add the last to the end of the list as is,
|
|
% without intersecting it with anything.
|
|
%
|
|
% If the input has N assoc lists, the output will have ceil(N/2) assoc
|
|
% lists. If invoked with two or more lists, the output will always have
|
|
% fewer assoc lists than the input. This will always be the case, since
|
|
% our caller does not call us when N<2.
|
|
%
|
|
:- pred intersect_list_pass(assoc_list(K, V), list(assoc_list(K, V)),
|
|
pred(V, V, V), assoc_list(K, V), list(assoc_list(K, V))).
|
|
:- mode intersect_list_pass(in, in, in(pred(in, in, out) is semidet), out, out)
|
|
is semidet.
|
|
:- mode intersect_list_pass(in, in, in(pred(in, in, out) is det), out, out)
|
|
is det.
|
|
|
|
intersect_list_pass(HeadAssocList, TailAssocLists, CommonPred,
|
|
FirstAssocList, LaterAssocLists) :-
|
|
(
|
|
TailAssocLists = [],
|
|
FirstAssocList = HeadAssocList,
|
|
LaterAssocLists = []
|
|
;
|
|
TailAssocLists = [HeadTailAssocList | TailTailAssocLists],
|
|
map.intersect_loop(HeadAssocList, HeadTailAssocList, CommonPred,
|
|
[], RevFirstAssocList),
|
|
list.reverse(RevFirstAssocList, FirstAssocList),
|
|
(
|
|
TailTailAssocLists = [],
|
|
LaterAssocLists = []
|
|
;
|
|
TailTailAssocLists =
|
|
[HeadTailTailAssocList | TailTailTailAssocLists],
|
|
map.intersect_list_pass(HeadTailTailAssocList,
|
|
TailTailTailAssocLists, CommonPred,
|
|
HeadLaterAssocList, TailLaterAssocLists),
|
|
LaterAssocLists = [HeadLaterAssocList | TailLaterAssocLists]
|
|
)
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
union(F, MapA, MapB) = UnionMap :-
|
|
P = (pred(X::in, Y::in, Z::out) is det :- Z = F(X, Y) ),
|
|
map.union(P, MapA, MapB, UnionMap).
|
|
|
|
union(CommonPred, MapA, MapB, UnionMap) :-
|
|
map.to_sorted_assoc_list(MapA, AssocListA),
|
|
map.to_sorted_assoc_list(MapB, AssocListB),
|
|
map.union_loop(AssocListA, AssocListB, CommonPred, [], RevUnionAssocList),
|
|
map.from_rev_sorted_assoc_list(RevUnionAssocList, UnionMap).
|
|
|
|
% The real intended modes of this predicate are the last two.
|
|
% The first four modes are just specialized versions for use by
|
|
% recursive calls after it has been determined that one or other input
|
|
% list has run out of elements. These specialized versions don't do
|
|
% redundant tests to see whether the known-empty list is empty or not.
|
|
%
|
|
:- pred union_loop(assoc_list(K, V), assoc_list(K, V), pred(V, V, V),
|
|
assoc_list(K, V), assoc_list(K, V)).
|
|
:- mode union_loop(in(bound([])), in, in(pred(in, in, out) is semidet),
|
|
in, out) is semidet.
|
|
:- mode union_loop(in(bound([])), in, in(pred(in, in, out) is det), in, out)
|
|
is det.
|
|
:- mode union_loop(in, in(bound([])), in(pred(in, in, out) is semidet),
|
|
in, out) is semidet.
|
|
:- mode union_loop(in, in(bound([])), in(pred(in, in, out) is det), in, out)
|
|
is det.
|
|
:- mode union_loop(in, in, in(pred(in, in, out) is semidet), in, out)
|
|
is semidet.
|
|
:- mode union_loop(in, in, in(pred(in, in, out) is det), in, out)
|
|
is det.
|
|
|
|
union_loop(AssocList1, AssocList2, CommonPred, !RevCommonAssocList) :-
|
|
(
|
|
AssocList1 = [],
|
|
AssocList2 = []
|
|
;
|
|
AssocList1 = [Key1 - Value1 | AssocTail1],
|
|
AssocList2 = [],
|
|
!:RevCommonAssocList = [Key1 - Value1 | !.RevCommonAssocList],
|
|
map.union_loop(AssocTail1, AssocList2, CommonPred, !RevCommonAssocList)
|
|
;
|
|
AssocList1 = [],
|
|
AssocList2 = [Key2 - Value2 | AssocTail2],
|
|
!:RevCommonAssocList = [Key2 - Value2 | !.RevCommonAssocList],
|
|
map.union_loop(AssocList1, AssocTail2, CommonPred, !RevCommonAssocList)
|
|
;
|
|
AssocList1 = [Key1 - Value1 | AssocTail1],
|
|
AssocList2 = [Key2 - Value2 | AssocTail2],
|
|
compare(R, Key1, Key2),
|
|
(
|
|
R = (=),
|
|
CommonPred(Value1, Value2, Value),
|
|
!:RevCommonAssocList = [Key1 - Value | !.RevCommonAssocList],
|
|
map.union_loop(AssocTail1, AssocTail2, CommonPred,
|
|
!RevCommonAssocList)
|
|
;
|
|
R = (<),
|
|
!:RevCommonAssocList = [Key1 - Value1 | !.RevCommonAssocList],
|
|
map.union_loop(AssocTail1, AssocList2, CommonPred,
|
|
!RevCommonAssocList)
|
|
;
|
|
R = (>),
|
|
!:RevCommonAssocList = [Key2 - Value2 | !.RevCommonAssocList],
|
|
map.union_loop(AssocList1, AssocTail2, CommonPred,
|
|
!RevCommonAssocList)
|
|
)
|
|
).
|
|
|
|
det_union(F, MapA, MapB) = UnionMap :-
|
|
P = (pred(X::in, Y::in, Z::out) is semidet :- Z = F(X, Y) ),
|
|
map.det_union(P, MapA, MapB, UnionMap).
|
|
|
|
det_union(CommonPred, MapA, MapB, UnionMap) :-
|
|
( if map.union(CommonPred, MapA, MapB, UnionMapPrime) then
|
|
UnionMap = UnionMapPrime
|
|
else
|
|
unexpected($pred, "map.union failed")
|
|
).
|
|
|
|
union_list(CommonPred, HeadMap, TailMaps, Common) :-
|
|
map.to_sorted_assoc_list(HeadMap, HeadAssocList),
|
|
list.map(map.to_sorted_assoc_list, TailMaps, TailAssocLists),
|
|
map.union_list_passes(HeadAssocList, TailAssocLists, CommonPred,
|
|
CommonAssocList),
|
|
map.from_sorted_assoc_list(CommonAssocList, Common).
|
|
|
|
:- pred union_list_passes(assoc_list(K, V), list(assoc_list(K, V)),
|
|
pred(V, V, V), assoc_list(K, V)).
|
|
:- mode union_list_passes(in, in, in(pred(in, in, out) is semidet), out)
|
|
is semidet.
|
|
:- mode union_list_passes(in, in, in(pred(in, in, out) is det), out)
|
|
is det.
|
|
|
|
union_list_passes(HeadAssocList, TailAssocLists, CommonPred,
|
|
CommonAssocList) :-
|
|
(
|
|
TailAssocLists = [],
|
|
CommonAssocList = HeadAssocList
|
|
;
|
|
TailAssocLists = [_ | _],
|
|
map.union_list_pass(HeadAssocList, TailAssocLists, CommonPred,
|
|
FirstAssocList, LaterAssocLists),
|
|
map.union_list_passes(FirstAssocList, LaterAssocLists, CommonPred,
|
|
CommonAssocList)
|
|
).
|
|
|
|
% This predicate works on the same principle as map.intersect_list_pass.
|
|
% See the documentation of that predicate.
|
|
%
|
|
:- pred union_list_pass(assoc_list(K, V), list(assoc_list(K, V)),
|
|
pred(V, V, V), assoc_list(K, V), list(assoc_list(K, V))).
|
|
:- mode union_list_pass(in, in, in(pred(in, in, out) is semidet), out, out)
|
|
is semidet.
|
|
:- mode union_list_pass(in, in, in(pred(in, in, out) is det), out, out)
|
|
is det.
|
|
|
|
union_list_pass(HeadAssocList, TailAssocLists, CommonPred,
|
|
FirstAssocList, LaterAssocLists) :-
|
|
(
|
|
TailAssocLists = [],
|
|
FirstAssocList = HeadAssocList,
|
|
LaterAssocLists = []
|
|
;
|
|
TailAssocLists = [HeadTailAssocList | TailTailAssocLists],
|
|
map.union_loop(HeadAssocList, HeadTailAssocList, CommonPred,
|
|
[], RevFirstAssocList),
|
|
list.reverse(RevFirstAssocList, FirstAssocList),
|
|
(
|
|
TailTailAssocLists = [],
|
|
LaterAssocLists = []
|
|
;
|
|
TailTailAssocLists =
|
|
[HeadTailTailAssocList | TailTailTailAssocLists],
|
|
map.union_list_pass(HeadTailTailAssocList, TailTailTailAssocLists,
|
|
CommonPred, HeadLaterAssocList, TailLaterAssocLists),
|
|
LaterAssocLists = [HeadLaterAssocList | TailLaterAssocLists]
|
|
)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
compose_maps(MapAB, MapBC, MapAC) :-
|
|
map.to_sorted_assoc_list(MapAB, AssocListAB),
|
|
compose_maps_loop(MapBC, AssocListAB, [], RevAssocListAC),
|
|
map.from_rev_sorted_assoc_list(RevAssocListAC, MapAC).
|
|
|
|
:- pred compose_maps_loop(map(B, C)::in, assoc_list(A, B)::in,
|
|
assoc_list(A, C)::in, assoc_list(A, C)::out) is det.
|
|
|
|
compose_maps_loop(_MapBC, [], !RevAssocListAC).
|
|
compose_maps_loop(MapBC, [A - B | ABs], !RevAssocListAC) :-
|
|
map.lookup(MapBC, B, C),
|
|
!:RevAssocListAC = [A - C | !.RevAssocListAC],
|
|
compose_maps_loop(MapBC, ABs, !RevAssocListAC).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
count(Map) = Count :-
|
|
tree234.count(Map, Count).
|
|
|
|
count(Map, Count) :-
|
|
tree234.count(Map, Count).
|
|
|
|
ucount(Map) = Count :-
|
|
tree234.ucount(Map, Count).
|
|
|
|
ucount(Map, Count) :-
|
|
tree234.ucount(Map, Count).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
equal(MapA, MapB) :-
|
|
tree234.equal(MapA, MapB).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
optimize(M0) = M :-
|
|
map.optimize(M0, M).
|
|
|
|
optimize(Map, Map).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
foldl(F, M, A) = B :-
|
|
P = (pred(W::in, X::in, Y::in, Z::out) is det :- Z = F(W, X, Y) ),
|
|
map.foldl(P, M, A, B).
|
|
|
|
foldl(Pred, Map, !A) :-
|
|
tree234.foldl(Pred, Map, !A).
|
|
|
|
foldl2(Pred, Map, !A, !B) :-
|
|
tree234.foldl2(Pred, Map, !A, !B).
|
|
|
|
foldl3(Pred, Map, !A, !B, !C) :-
|
|
tree234.foldl3(Pred, Map, !A, !B, !C).
|
|
|
|
foldl4(Pred, Map, !A, !B, !C, !D) :-
|
|
tree234.foldl4(Pred, Map, !A, !B, !C, !D).
|
|
|
|
foldl5(Pred, Map, !A, !B, !C, !D, !E) :-
|
|
tree234.foldl5(Pred, Map, !A, !B, !C, !D, !E).
|
|
|
|
foldl6(Pred, Map, !A, !B, !C, !D, !E, !F) :-
|
|
tree234.foldl6(Pred, Map, !A, !B, !C, !D, !E, !F).
|
|
|
|
%---------------------%
|
|
|
|
foldl_values(Pred, Map, !A) :-
|
|
tree234.foldl_values(Pred, Map, !A).
|
|
|
|
foldl2_values(Pred, Map, !A, !B) :-
|
|
tree234.foldl2_values(Pred, Map, !A, !B).
|
|
|
|
foldl3_values(Pred, Map, !A, !B, !C) :-
|
|
tree234.foldl3_values(Pred, Map, !A, !B, !C).
|
|
|
|
foldl4_values(Pred, Map, !A, !B, !C, !D) :-
|
|
tree234.foldl4_values(Pred, Map, !A, !B, !C, !D).
|
|
|
|
foldl5_values(Pred, Map, !A, !B, !C, !D, !E) :-
|
|
tree234.foldl5_values(Pred, Map, !A, !B, !C, !D, !E).
|
|
|
|
foldl6_values(Pred, Map, !A, !B, !C, !D, !E, !F) :-
|
|
tree234.foldl6_values(Pred, Map, !A, !B, !C, !D, !E, !F).
|
|
|
|
%---------------------%
|
|
|
|
foldr(F, M, A) = B :-
|
|
P = (pred(W::in, X::in, Y::in, Z::out) is det :- Z = F(W, X, Y) ),
|
|
map.foldr(P, M, A, B).
|
|
|
|
foldr(Pred, Map, !A) :-
|
|
tree234.foldr(Pred, Map, !A).
|
|
|
|
foldr2(Pred, Map, !A, !B) :-
|
|
tree234.foldr2(Pred, Map, !A, !B).
|
|
|
|
foldr3(Pred, Map, !A, !B, !C) :-
|
|
tree234.foldr3(Pred, Map, !A, !B, !C).
|
|
|
|
foldr4(Pred, Map, !A, !B, !C, !D) :-
|
|
tree234.foldr4(Pred, Map, !A, !B, !C, !D).
|
|
|
|
foldr5(Pred, Map, !A, !B, !C, !D, !E) :-
|
|
tree234.foldr5(Pred, Map, !A, !B, !C, !D, !E).
|
|
|
|
foldr6(Pred, Map, !A, !B, !C, !D, !E, !F) :-
|
|
tree234.foldr6(Pred, Map, !A, !B, !C, !D, !E, !F).
|
|
|
|
%---------------------%
|
|
|
|
map_values(F, M0) = M :-
|
|
P = (pred(X::in, Y::in, Z::out) is det :- Z = F(X, Y) ),
|
|
map.map_values(P, M0, M).
|
|
|
|
map_values(Pred, Map0, Map) :-
|
|
tree234.map_values(Pred, Map0, Map).
|
|
|
|
map_values_only(F, M0) = M :-
|
|
P = (pred(Y::in, Z::out) is det :- Z = F(Y) ),
|
|
map.map_values_only(P, M0, M).
|
|
|
|
map_values_only(Pred, Map0, Map) :-
|
|
tree234.map_values_only(Pred, Map0, Map).
|
|
|
|
filter_map_values(Pred, Map0, Map) :-
|
|
tree234.filter_map_values(Pred, Map0, Map).
|
|
|
|
filter_map_values_only(Pred, Map0, Map) :-
|
|
tree234.filter_map_values_only(Pred, Map0, Map).
|
|
|
|
%---------------------%
|
|
|
|
map_foldl(Pred, !Map, !AccA) :-
|
|
tree234.map_foldl(Pred, !Map, !AccA).
|
|
|
|
map_foldl2(Pred, !Map, !AccA, !AccB) :-
|
|
tree234.map_foldl2(Pred, !Map, !AccA, !AccB).
|
|
|
|
map_foldl3(Pred, !Map, !AccA, !AccB, !AccC) :-
|
|
tree234.map_foldl3(Pred, !Map, !AccA, !AccB, !AccC).
|
|
|
|
map_foldl4(Pred, !Map, !AccA, !AccB, !AccC, !AccD) :-
|
|
tree234.map_foldl4(Pred, !Map, !AccA, !AccB, !AccC, !AccD).
|
|
|
|
%---------------------%
|
|
|
|
map_values_foldl(Pred, !Map, !AccA) :-
|
|
tree234.map_values_foldl(Pred, !Map, !AccA).
|
|
|
|
map_values_only_foldl(Pred, !Map, !AccA) :-
|
|
tree234.map_values_only_foldl(Pred, !Map, !AccA).
|
|
|
|
map_values_foldl2(Pred, !Map, !AccA, !AccB) :-
|
|
tree234.map_values_foldl2(Pred, !Map, !AccA, !AccB).
|
|
|
|
map_values_only_foldl2(Pred, !Map, !AccA, !AccB) :-
|
|
tree234.map_values_only_foldl2(Pred, !Map, !AccA, !AccB).
|
|
|
|
map_values_foldl3(Pred, !Map, !AccA, !AccB, !AccC) :-
|
|
tree234.map_values_foldl3(Pred, !Map, !AccA, !AccB, !AccC).
|
|
|
|
map_values_only_foldl3(Pred, !Map, !AccA, !AccB, !AccC) :-
|
|
tree234.map_values_only_foldl3(Pred, !Map, !AccA, !AccB, !AccC).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
old_merge(MapA, MapB) = MergedMap :-
|
|
map.old_merge(MapA, MapB, MergedMap).
|
|
|
|
old_merge(MapA, MapB, MergedMap) :-
|
|
map.to_assoc_list(MapA, ListA),
|
|
map.to_assoc_list(MapB, ListB),
|
|
list.merge(ListA, ListB, MergedList),
|
|
% MergedList will be sorted, but it may contain duplicates.
|
|
map.from_assoc_list(MergedList, MergedMap).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module map.
|
|
%---------------------------------------------------------------------------%
|