[m-users.] Problem with unique modes

Zoltan Somogyi zoltan.somogyi at runbox.com
Sun Jul 25 02:22:03 AEST 2021


2021-07-23 11:27 GMT+10:00 "Ricardo Correia" <lists.mercurylang.org at wizy.org>:
> However, I'm not entirely sure how to make type `state` unique.

Due to limitation mentioned in the LIMITATIONS file, you can't.

> Then, I tried to do what the `hash_table` standard library module does,
> I think, by declaring an instantiation (?) and some custom `sdi` and
> `suo` modes, because `hash_table` is also a type which has some integers
> and a vector (which also has to be unique) so I assumed my type was
> similar enough.

The top of the hash_table library module does mention the fact
that updates to hash tables should not be backtracked over, and why,
and the fact that the compiler won't detect those errors.

> This compiled fine but then the program fails with an exception because
> (as far as I can see) when backtracking, the integer fields within the
> `state` type do backtrack but the hash table doesn't.

That is correct.

> I am guessing that this is related to the first limitation mentioned in
> the `LIMITATIONS` file and in the hash table module -- specifically,
> that the Mercury compiler doesn't handle nested unique modes yet.

That is also true.

> My questions are:
> 
> 1. Is my understanding above correct?

Yes.
 
> 2. Are there still plans to fix nested unique modes? Also, is this
> something that is being worked on?

Vague plans, but nothing concrete. Support for partially instantiated
data structures and nested unique modes turned out to be way less important
in practice than we originally thought, for most uses of Mercury. You are
just unfortunate to fall outside this category of "most uses".

> 3. Is there a way to still use hash tables or vectors within other types
> somewhat safely, i.e. in a way that the compiler warns if the code
> may backtrack unexpectedly, like it usually happens with the `io` type?

At the moment, it is up to the user to avoid backtracking over updates
that are (a) implemented destructively, but (b) described to the compiler
using non-destructive modes, such as the mode aliasas in array.m and
hash_table.m, and your error.m. Since the compiler does not know that
these updates are in fact destructive, it cannot warn about those updates
being backtracked over.

If you lie to the compiler, no matter how necessary the lie, don't be
surprised if the compiler believes you.

> These are the issues in the first limitation that I am struggling with:
> 
> 1. It says that "definite aliasing" is "not allowed", however I still
> don't quite understand what "definite aliasing" is

It is allowing two free variables to be unified, which means that they become
aliases of each other. If e.g. X is unified with Y while both are free variables,
then binding X to a term, such as f(a, b), will bind Y to f(a, b) as well,
as a form of what Einstein called "spooky action at a distance". It is such
"action at a distance" that the Mercury compiler cannot handle.

I have just committed a change to LIMITATIONS that should explain that.

> or what
> "is not allowed" means (does the compiler give a warning or error in
> this case or is the program simply miscompiled?).

The program won't be miscompiled, nor will it give a warning. Whether
you get an error or not depends on whether mode analysis finds a way
to reorder whatever conjunction contains X = Y to delay that unification
until at least one of X and Y is ground. If it finds such a reordering,
then there is no aliasing needed, and the code will be compiled, and will work.
If it does not find a reordering, it will give you an error message.

> 2. It says that "partial instantiation" and "nested unique modes" are
> "unusable", but again, it doesn't explain what "partial instantiation"
> means

A partially instantiated term is one that contains both function symbols
and free variables. It is the middle of a spectrum, at one end of which
are free variables, and the other end ground terms.

> nor what "unusable" means in this case.

It means that in most use cases, the compiler won't find the reordering
described above, and will reject your program.

> Again, does the compiler
> give a warning or error or is the program simply miscompiled?

Same answer as above.

> 3. It then gives a detailed explanation, but I'm not sure if the detailed
> explanation refers to the whole "definite aliasing" limitation or only to
> the "partial instantiation working by chance" issue.

I don't understand what you mean by that.
 
> 4. The detailed explanation talks about scope, but again I don't know
> what scope means in this case (what other scopes are there?)

The rewording should explain that.

> 5. It refers to Mantis bug 311, which seems to have nothing to do with
> nested unique modes, I think.

No, it does not, but it does involve partially instantiated terms.

> 6. The first limitation would be much clearer if there were some
> examples of code which works (including the special case mentioned in
> the detailed explanation)

That special case has no useful use case.

> and code which should work but doesn't (and
> whether it doesn't because the compiler fails or because the program
> will misbehave at runtime).

My just committed diff to LIMITATIONS has such an example.

I would advise learning Mercury using purely functional data structures first,
and only switching to destructively updated data structures once you have got
the hand of the language. Starting with hash tables is like starting swimming
lessons at the deep end instead of in the kiddie pool.

Zoltan.


More information about the users mailing list