[m-dev.] for review: impure functions

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Apr 6 15:04:29 AEST 2000


On 04-Apr-2000, Tyson Dowd <trd at cs.mu.OZ.AU> wrote:
> Impure functions can be declared just like impure preds.
> However, they can only be called in an explicit unification preceeded
> by a purity level:
> 
> 	impure X = some_impure_func(Y, Z)

It would be much nicer if that syntax could be

	X = impure some_impure_func(Y, Z)

> +++ compiler/make_hlds.m	2000/03/27 07:59:41
> @@ -5052,8 +5052,8 @@
>  		{ Args0 = [LHS, RHS] }
>  	->
>  			% `LHS \= RHS' is defined as `not (RHS = RHS)'

That should be

  			% `LHS \= RHS' is defined as `not (LHS = RHS)'
							   ^

> +++ compiler/notes/authors.html	2000/03/24 04:00:12
> @@ -46,6 +46,8 @@
>  <tr>
>  <td>petdr	<td>Peter Ross		<td>petdr at cs.mu.oz.au </tr>
>  <tr>
> +<td>scachte	<td>Peter Schachte	<td>schachte at cs.mu.oz.au </tr>
> +<tr>

s/scachte/schachte/
            ^

> +++ doc/reference_manual.texi	2000/04/04 08:23:01
> @@ -4626,10 +4626,10 @@
>  unless declared otherwise (@pxref{Impurity}), and they must
>  be type-correct and mode-correct.  (Determinism-correctness
>  is also required, but it follows from the rules already stated
> -above.)  They may perform destructive update on their
> +above.)  Pure procedures may perform destructive update on their
>  arguments only if those arguments have an appropriate
>  unique mode declaration.

That change is wrong; this restriction applies to *all* procedures, not just
pure ones.

> -They may perform I/O only if their arguments
> +Pure procedures may perform I/O only if their arguments
>  include an @samp{io__state} pair (see the @samp{io} chapter
>  of the Mercury Library Reference Manual).

This is correct, but it applies to semipure procedures too.
I suggest you change that to

    They may perform I/O only if their arguments
    include an @samp{io__state} pair (see the @samp{io} chapter
    of the Mercury Library Reference Manual), or if they
    are declared impure (@pxref{Impurity}).

>  The Mercury implementation is allowed to assume that
> @@ -4663,6 +4663,11 @@
>  to this procedure, which could effect the behaviour
>  of the program in unpredictable ways.
>  
> +Impure C code relaxes some of these restrictions.  
> +Impure C code may perform I/O and although it cannot update its
> +arguments directly it may update something pointed to by its arguments.

Saying that it "cannot update its arguments directly"
is not correct; it _can_ update its arguments directly,
if they have mode `di'.

> @@ -5336,22 +5341,24 @@
>  
>  One important aim of Mercury's impurity system is to make the
>  distinction between the pure and impure code very clear.  This is done
> -by requiring every impure predicate to be so declared, and by requiring
> -every call to an impure predicate to be flagged as such.  Predicates
> -that are implemented in terms of impure predicates are assumed to be
> -impure themselves unless they are explicitly promised to be pure.
> +by requiring every impure predicate or function to be so declared, and
> +by requiring every call to an impure predicate to be flagged as such.

Shouldn't calls to impure functions be flagged too?

>  @menu
>  * Purity levels::       Choosing the right level of purity.
> +* Purity ordering::     How purity levels are ordered 
>  * Impurity semantics::  What impure code means.
>  * Declaring impurity::  Declaring predicates impure.
>  * Impure calls::        Marking a call as impure.
> @@ -5372,13 +5379,15 @@
>  input/output) without taking an io__state (@pxref{Types}) as input and
>  returning one as output, and do not make any changes to any data
>  structure that will not be undone on backtracking (unless the data
> -structure would be unreachable on backtracking).  The behaviour of other
> -predicates is never affected by the invocation of pure predicates, nor
> -is the behaviour of pure predicates ever affected by the invocation of
> -other predicates.
> +structure would be unreachable on backtracking).  The behaviour of pure
> +predicates is never affected by the invocation of pure predicates.
> +It is possible for the invocation of pure predicate to affect the
> +behaviour of non-pure predicates and vice versa.

That change misses the point.  The sentence "The behaviour of pure predicates
is never affected by the invocation of pure predicates" is not correct.
For pure procedures with determinism `cc_nondet' or `cc_multi',
the invocation of other pure predicates can affect which solution
you get.  For pure procedures with determinism `nondet' or `multi',
the invocation of other pure predicates can affect the order in
which the solutions are returned.  And for all pure procedures,
the invocation of other pure procedures can affect whether you
get a solution at all, or whether you get non-termination,
an exception, or a run-time abort.

I'm not sure if there is any way of salvaging that text;
perhaps it would be best to just delete it.

Also the sentence at the start of the paragraph

	 Pure predicates and functions always return the same outputs given
	 the same inputs.

is not correct for procedures with determinism `cc_nondet' or `cc_multi'.

I suggest changing that sentence to

	For pure procedures, the set of solutions depends only on the
	values of the input arguments.

>  @node Declaring impurity
> - at section Declaring predicate impurity
> + at section Declaring impure functions and predicates
...
>  A predicate is declared to be impure or semipure by preceding the word
>  @code{pred} in its @code{pred} declaration with @code{impure}

You need a similar statement for functions.

> @@ -5449,22 +5474,46 @@
>  or
>  
>  @example
> -:- semipure pred @var{Pred}(@var{Arguments}@dots{}).
> +:- semipure func @var{Pred}(@var{Arguments}@dots{}) = (Result).
>  @end example

I think that should be @var{Func} not @var{Pred}.

Why the parentheses around `Result'?

>  @noindent
> -declares the predicate @var{Pred} to be impure or semipure, respectively.
> +declares the predicate @var{Pred} to be impure and the function
> + at var{Func} to be semipure, respectively.

Since the text says "That is, a declaration of the form ...", you should
either give all four possible such forms (pure pred, pure func, semipure
pred, semipure func), rather than just giving two of them,
or change "This is" to "For example".  Of these two alternatives,
I think the former is the better one.

> +Type class methods may also be declared as @code{impure} or
> + at code{semipure} by preceeding the word @code{pred} or @code{func} with the
> +appropriate purity level.  An instance of the type class must provide
> +method implementations that are at least as pure as the method
> +declaration. 

In the section earlier, you say that you describe purity ordering
as "worse"/"better", but here and elsewhere you just talk about it as
"more pure" or "less pure".  I think you should delete the description

> +It is an error for the declared purity of a goal to be more pure than
> +the inferred purity, the compiler should flag this as an error.

s/,/;/

Or alternatively s/,.*/./

> +++ tests/invalid/type_inf_loop.err_exp2	2000/04/04 07:58:24
> @@ -7,4 +7,8 @@
>  (The current limit is 60 iterations.  You can use the
>  `--type-inference-iteration-limit' option to increase the limit).
>  type_inf_loop.m:004: Inferred :- pred loop((pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred (pred T1))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))).
> +type_inf_loop.m:004: Unable to purity check this unification.
> +type_inf_loop.m:004:   The purity of the higher order term is unknown.
> +type_inf_loop.m:004:   This can occur if type inference fails.
> +type_inf_loop.m:004:   You should declare the types explicitly.

The extra error message here is just confusing; it does not help the
programmer at all, IMHO.  I agree with DJ: it would be better to not
report errors during purity analysis in such cases.

> +++ impure_func_t2.err_exp	Sun Mar 26 17:53:07 2000
> @@ -0,0 +1,4 @@
> +impure_func_t2.m:016: In call to impure function `impure_func_t2:get_counter/0':
> +impure_func_t2.m:016:   error: call must be in an explicit unification
> +impure_func_t2.m:016:   which is preceded by `impure' indicator.

It might be nicer if the error message specified which of these
two conditions was not satisfied.

> +purity.m:059: In predicate `purity:e1/0':
> +purity.m:059:   error: predicate is impure.
> +purity.m:059:   It must be declared `impure' or promised pure.
> +purity.m:064: In predicate `purity:e2/0':
> +purity.m:064:   error: predicate is semipure.
> +purity.m:064:   It must be declared `semipure' or promised pure.
> +purity.m:068: In predicate `purity:e3/0':
> +purity.m:068:   error: predicate is impure.
> +purity.m:068:   It must be declared `impure' or promised pure.
> +purity.m:074: In call to impure predicate `purity:imp/0':
> +purity.m:074:   error: call must be preceded by `impure' indicator.
> +purity.m:078: In call to semipure predicate `purity:semi/0':
> +purity.m:078:   error: call must be preceded by `semipure' indicator.

I suggest s/error:/purity error:/g

> +purity.m:112: Error in closure: closure is impure.
> +purity.m:118: Error in closure: closure is semipure.

I suggest s/Error:/Purity error:/g

> Index: tests/invalid/purity/purity_nonsense.err_exp
> ===================================================================
> RCS file: purity_nonsense.err_exp
> diff -N purity_nonsense.err_exp
> --- /dev/null	Thu Mar  4 04:20:11 1999
> +++ purity_nonsense.err_exp	Wed Nov 10 09:40:13 1999
> @@ -0,0 +1,47 @@
> +purity_nonsense.m:003: Error: invalid impurity declaration: func undefined_func = foo.
...
> +:- impure func undefined_func = foo.		% no impure functions (yet)

As DJ said, the error message for that line looks wrong.

-- 
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 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list