[m-users.] Question regarding predicates stored in existential data types.

Zoltan Somogyi zoltan.somogyi at runbox.com
Wed Feb 17 14:23:00 AEDT 2021

2021-02-17 13:57 GMT+11:00 "Philip White" <philip at pswhite.org>:
> Hello,
> below is the type I have:
> :- type flag(T)
>    --->    flag(                 flag_doc :: string,                 flag_name :: string,
>                flag_kind :: flag_kind(T)             )
>    ;       return_flag(T)
>    ;       some [A] map1_flag(flag(A), pred(A::in, T::out) is det)
>    ;       some [A, B]	map2_flag(flag(A), flag(B), pred(A::in, B::in, T::out) is det).
> When I deconstruct a value in the map2_flag case, and then try to call
> it, I'm getting the error:
> variable F [the variable that corresponds to the predicate part the
> value] has instiatedness `ground', expecting higher-order pred inst of
> arity 3.
> Is the problem that 'ground' is not the same as pred(in, in, out) is
> det? 

Yes, that would be the problem.

>  tried making a new inst for flag that makes everything ground,
> except the predicate part, for which it uses a predicate instantiation.
> However, this turned into a mess of errors, so I'm not sure if I'm even
> on the right track.

Unless you show us the instantiation you used, we can't be sure either.

Have look at the declaration of e.g. take_while in list.m in the Mercury
standard library. That is the kind of inst that you need, though in your case
you would need an inst for the whole flag(T) type, of which the predicate
is only a part.

> One thing I don't understand is why there needs to be a separate kind
> of inst predicates. Why are ground and free not enough? 

When you do an ordinary, first-order call to a predicate, the compiler
gets its mode (or modes) from its declaration, or from inference.
When you call a higher order value, neither of these sources is available,
so the compiler has no way to know what the modes of the arguments are,
unless you tell it. Higher order insts are the way in which users can do that.
Without this, or something very similar, how would the compiler know
that the modes of the predicate's arguments are supposed to be in, in, out?

The "map2_flag(flag(A), flag(B), pred(A::in, B::in, T::out) is det)" fills the bill
of "something very similar", and indeed, the compiler *should* be able
to get the mode of the higher order value in the third arg of map2_flag
from there. But while the compiler allows such mode (and determinism)
information to be included in  type definitions, as in your example,
this is a relatively recent addition to the language, and its support
is not yet complete. Specifically, the mode analyser still gets its
information about the modes of the arguments of higher order values
only from higher order insts in mode declarations, not from higher order
insts in type declarations. This is why you get the error you get.

Once this limitation is lifted, the code you wrote *should* be accepted
by the compiler as is. Unfortunately, noone is working on this right now.


More information about the users mailing list