[mercury-users] map__foldl2

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Dec 17 01:11:58 AEDT 1999

On 13-Dec-1999, Dominique de Waleffe <ddw at miscrit.be> wrote:
> I wanted to have a map__foldl2 with the 2nd accumulator being the io__state.
> I did not want to reimplement the whole thing down to the tree234 library.
> So I attempted to use the following code :
> :- module mapx.
> :- interface.
> :-import_module map.
> :- pred mapx__foldl2(pred(K, V, T, T,TT,TT), map(K, V), T, T,TT,TT).
> :- mode mapx__foldl2(pred(in, in, in, out, in, out) is det,
> 		     in, in, out, in, out) is det.
> :- mode mapx__foldl2(pred(in, in, in, out, di, uo) is det,
> 		     in, in, out, di, uo) is det.
> :- implementation.
> :- import_module std_util.
> :- inst inst1 = bound(ground-unique ; ground-ground).
> :- inst inst2 = bound(ground-dead; ground-ground).
> :-mode indi :: inst1 ->inst2.
> :-inst inst4 = bound(ground-unique;ground-ground).
> :-mode outuo :: free -> inst4.
> mapx__foldl2(P,M,L0,L,LL0,LL):-
> 	map__foldl((pred(K::in,V::in,A0::indi,A::outuo) is det:-
> 		    A0=AL0-ALL0,
> 		    P(K,V,AL0,AL,ALL0,ALL),
> 		    A=AL-ALL),
> 		   M,L0-LL0,L-LL).
> :- end_module mapx.
> Of course, the compiler does not it :-)
> mapx.m:030: In clause for `foldl2((pred(in, in, in, out, in, out) is det),
> in, in, out, in, out)':
> mapx.m:030:   in call to predicate `map:foldl/4':
> mapx.m:030:   mode error: arguments [...] have insts [...]
> mapx.m:030:   which do not match any of the modes for predicate `map:foldl/4'.
> mapx.m:032: In clause for `foldl2((pred(in, in, in, out, di, uo) is det),
> in, in, out, di, uo)':
> mapx.m:032:   in argument 6 (i.e. argument 5 of the called predicate) of
> higher-order predicate call:
> mapx.m:032:   mode error: variable `ALL0' has instantiatedness `ground',
> mapx.m:032:   expected instantiatedness was `unique'.

There's actually several different problems here.
A couple of these have already been discussioned:

  - One is that you're trying to call map__foldl in a mode other
    than its declared modes.  That is what leads to the first
    error message.

    In the long term, some kind of support for polymorphic modes
    would be desirable.  Then map__foldl in the library could
    have a more general mode declaration.  But we don't have any
    immediate plans for that.  Perhaps for Mercury 2.0...

  - Another is that the mode declaration

	:- inst inst1 = bound(ground-unique ; ground-ground).

    is not valid since it uses '-'/2 twice.  The compiler ought to reject it.
    That should not be too hard to fix; it won't be fixed in 0.9 but
    hopefully it should be fixed sometime soon after that; e.g. we might
    make a 0.9.1 release and if so, it might be fixed in that.

  - Clearly what you were trying to do with the above mode declaration
    was to write multiple mode declarations in one.  That won't
    work.  Since the compiler doesn't do mode inference for higher-order
    terms, there's no easy way of writing wrappers for higher-order
    multi-moded predicates.  It is possible -- see the code in
    library/exception.m for an example -- but I'm afraid it's not elegant.

    We don't have any immediate plans to add mode inference for
    higher-order terms.  Perhaps for Mercury 2.0...

    But allowing different code for different modes (in Mercury,
    rather than only when using the C interface) would make this
    kind of thing much simpler.  There'd be a bit of code duplication,
    with the only difference between the code in different modes
    being the mode annotations on the higher-order terms, but still
    it wouldn't be too bad.  And that feature would be easy to add.
    There's probably a good chance that support for different code
    in different modes will it into Mercury 1.0.

There are also some additional problems, which have not been
discussed in earlier messages in this thread.  These problems
are responsible for the second error message above:

  - Even if you restrict it to one mode at a time, i.e.

	:- inst inst1 = bound(ground - unique).
	:- inst inst2 = bound(ground - dead).
	:- mode indi :: inst1 ->inst2.
	:- inst inst4 = bound(ground - unique).
	:- mode outuo :: free -> inst4.

    those insts declaration are still not correct.  For any part
    of a data structure to be `unique', the top-level
    must be unique.  So it should be

	:- inst inst1 = unique(ground - unique).
	:- mode indi :: inst1 -> dead.
	:- inst inst4 = unique(ground - unique).
	:- mode outuo :: free -> inst4.

  - Nested unique modes are not yet supported.
    So if you try this, it won't work.

    Our intent is to fix this in Mercury 1.0.

Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at        |     -- the last words of T. S. Garp.
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe

More information about the users mailing list