[m-users.] Returning a predicate from a function

Mark Clements mark.clements at ki.se
Mon Dec 26 20:47:30 AEDT 2022


As a follow-up, I was interested in the speed and memory requirements for lists compared with nondet predicates. I set up an experiment to sum the integers between 1 and 10 million (yes, I know that there is closed form solution:). The code is here: https://gist.github.com/mclements/b09eee918c24710f59a2eb3a6a0a7a90. I found:
1. foldl using range(1,10000000) was the least time and used the least maximum resident memory
2. unsorted_aggregate with promise_equivalent_solutions was 3 x least time and similar memory
3. foldl using 1..10000000 was 6 x least time and 5 x least memory
4. foldl using unsorted_solutions and promise_equivalent_solutions was 8 x least time and 5 x least memory
5. aggregate was 150 x least time and 13 x least memory.

Note that aggregate creates a sorted list and then uses foldl. Sorting a large (already sorted) list is apparently very slow. For operations on nondet predicates that give equivalent solutions irrespective of the order, then using promise_equivalent_solutions looks helpful.

I realise that this experiment may not generalise to most Mercury programs.

Sincerely, Mark.

PS: the following two functions may be of interest.

%% map a function to a predicate, returning a new predicate
:- func map_pred((func(T1)=T2)::in(func(in)=out is det),
                 pred(T1)::(pred(out) is nondet)) =
   (pred(T2)::(out(pred(out) is nondet))).
map_pred(F,Pred) = (pred(Y::out) is nondet :- Pred(X), Y = F(X)).

%% compose two functions, returning a new function
:- func ((func(T1)=T2)::in(func(in)=out is det)) `o` ((func(T2)=T3)::in(func(in)=out is det)) =
   (func(T1)=T3::(out(func(in)=out is det))).
F `o` G = (func(X::in) = (R::out) is det :- R = G(F(X))).

%% Examples:

:- pred test3(io::di, io::uo) is det.
test3(!IO) :-
    Data = (pred(Y::out) is nondet :- nondet_member(I,range(1,5)), Y = float(I)), % some data
    LnData = map_pred(math.ln,Data),
    aggregate(LnData, print_line, !IO).
:- pred test4(io::di, io::uo) is det.
test4(!IO) :-
    List = map(float `o` math.ln, 1..5),
    foldl(print_line, List, !IO).


När du skickar e-post till Karolinska Institutet (KI) innebär detta att KI kommer att behandla dina personuppgifter. Här finns information om hur KI behandlar personuppgifter<https://ki.se/medarbetare/integritetsskyddspolicy>.


Sending email to Karolinska Institutet (KI) will result in KI processing your personal data. You can read more about KI’s processing of personal data here<https://ki.se/en/staff/data-protection-policy>.


More information about the users mailing list