[m-users.] Impurity needed?

Zoltan Somogyi zoltan.somogyi at runbox.com
Tue Feb 14 00:40:25 AEDT 2023


2023-02-14 00:24 GMT+11:00 "Volker Wysk" <post at volker-wysk.de>:

> The type of the odbc.transaction predicate is:
> 
> :- pred odbc.transaction(data_source::in, user_name::in, password::in,
>      transaction(T)::transaction, odbc.result(T)::out, io::di, io::uo) 
> is det.
> 
> 
> Would it be possible to just change the transaction type from this:
> 
> :- type odbc.transaction(T) ==  pred(T, odbc.state, odbc.state).
> :- mode odbc.transaction ==  (pred(out, di, uo) is det).
> 
> 
> To this:
> 
> 
> :- type odbc.transaction(T) ==  
>      pred(T, odbc.state, odbc.state, io.state, io.state).
> :- mode odbc.transaction ==  (pred(out, di, uo, di, uo) is det).
> 
> 
> So the transaction predicate can do IO, when called. This looks rather easy,
> but I'm not sure I've understood correctly.

It would be trivial to change the signature as you ask. It would also be
a very bad idea to do so. The point of making an operation a transaction
is to ensure that only two things can happen:

- the transaction succeeds, and ALL of its effects happen, or
- the transaction fails, and NONE of its effects happen.

If you allowed I/O in the middle of a transaction, and then later
it turned out that the transaction cannot succeed, then neither
of those end states would be reachable.

For more about why transaction predicate is designed the way it is,
have a look at the paper

- Database transactions in a purely declarative logic programming language

which is available at https://mercurylang.org/documentation/papers.html#mu_96_45

In your use case, you propose to do I/O only to read from a file; you don't
intend to update the state of the world. In such cases, using impure code
to read in the file, and wrapping a promise_pure scope around that code
to signify that the impure code implements a pure interface, would be ok.

Zoltan.

Zoltan.


More information about the users mailing list