[mercury-users] Can this be done better?

Julien Fischer juliensf at csse.unimelb.edu.au
Tue Jan 31 03:31:22 AEDT 2012

On Mon, 30 Jan 2012, Michael Richter wrote:

> On 30 January 2012 22:03, Julien Fischer <juliensf at csse.unimelb.edu.au>wrote:
>> The compiler's support for inst subtyping like this is a bit flakey.
>> Nevertheless, it's possible to write a version of apply/3 that only
>> accepts input lists of even length -- depending on the circumstances
>> it may not be possible to call it however.
> That sounds ominousÿÿ  :)

In practice, it's not that much of a problem.

>>    :- inst evenlist == bound([] ; [ground | oddlist]).
>>    :- inst oddlist  == bound([ground | evenlist])
> That's the kind of stuff I was toying with, but ÿÿ
>> Unfortunately, the above won't work since to use the new definition the
>> _compiler_ needs to be able to prove that the output of the call to
>> list.zip/2 also has the inst evenlist.  (Which is not possible given
>> the definition of zip/2.)
> ÿÿthis was the bar my head kept hitting.

I think list.zip/2 is not the right thing to be using here in any case.
You want to ensure that both lists have the same size, since each
function is required to have its inverse, and list.zip/2 won't do that.


>>    main(!IO) :-
>>        Forward = [math.sin, math.cos, (func(X) = math.ln(X))],
>>        Reverse = [math.asin, math.acos, (func(X) = math.exp(X))],
>>        apply(assoc_list.from_corresponding_lists(Forward, Reverse),
>>            [], Results),
>>        io.write_list(Results, ", ", io.write_float, !IO),
>>        io.write_string("\n", !IO).
>>     :- pred apply(assoc_list((func(float) = float)), list(float),
>>       list(float)).
>>     :- mode apply(in, in, out) is det.
>>    apply([], A, Results) :- Results = A.
>>    apply([F - R | Functions], A, Results) :-
>>        apply(Functions, [compose(R, F, 0.5) | A], Results).
> I'm not sure I understand this one at all, however.  I mean I understand my
> apply/3 predicate still, even with the funky F - R match there, but would
> you mind walking me through the rest of this a bit?

It uses the standard library's assoc_list/2 type, which is defined (in
the module assoc_list) as:

    :- type assoc_list(K, V) == list(pair(K, V)).
    :- type assoc_list(T) == list(pair(T, T)).

We call the function ssoc_list.from_corresponding_lists/2 in place of
list.zip/2 and this generates a list of pairs of functions from the
Forward and Reverse lists.  apply/3 then just walks over that list
of pairs and everything else is unchanged.
(from_corresponding_lists/2 behaves more like Haskell's zip function
than Mercury's list.zip/2 function.)


More information about the users mailing list