[m-dev.] Re: [m-rev.] for review: io__action_sequenceN
David Overton
dmo at cs.mu.OZ.AU
Fri May 25 17:58:12 AEST 2001
On Fri, May 25, 2001 at 02:09:52PM +1000, Zoltan Somogyi wrote:
> +% I/O "combinators".
> +
> +% Each of these predicates takes is inputs N I/O actions, and a predicate that
> +% combines the results of these actions into a single result.
> +%
> +% They return ok if all the actions succeeded. They return error if an action
> +% resulted in an error after the previous ones succeeded, and they return eof
> +% if one of the actions found eof after the previous ones succeeded. In either
> +% case, the inputs of those earlier successful actions have already been
> +% consumed, but their results are not returned.
> +
> +:- pred io__action_sequence2(
> + pred(io__result(T1), io__state, io__state),
> + pred(io__result(T2), io__state, io__state),
> + pred(T1, T2, io__result(T)),
> + io__result(T), io__state, io__state).
> +:- mode io__action_sequence2(
> + pred(out, di, uo) is det,
> + pred(out, di, uo) is det,
> + pred(in, in, out) is det,
> + out, di, uo) is det.
> +
> +:- pred io__action_sequence3(
> + pred(io__result(T1), io__state, io__state),
> + pred(io__result(T2), io__state, io__state),
> + pred(io__result(T3), io__state, io__state),
> + pred(T1, T2, T3, io__result(T)),
> + io__result(T), io__state, io__state).
> +:- mode io__action_sequence3(
> + pred(out, di, uo) is det,
> + pred(out, di, uo) is det,
> + pred(out, di, uo) is det,
> + pred(in, in, in, out) is det,
> + out, di, uo) is det.
[...]
Hi,
I've been thinking about how we might be able to do something similar
to this whilst avoiding having to write a whole bunch of similar
predicates for different numbers of actions.
I had a think about using a higher order combinator approach and came
up with the following. Comments would be appreciated.
----------------------
:- func then(pred(io__result(T1), io__state, io__state),
pred(io__result(T2), io__state, io__state)) =
pred(io__result(pair(T1, T2)), io__state, io__state).
:- mode then(pred(out, di, uo) is det, pred(out, di, uo) is det) =
out(pred(out, di, uo) is det) is det.
P1 `then` P2 =
( pred(R::out, di, uo) is det -->
P1(R1),
(
{ R1 = ok(T1) },
P2(R2),
(
{ R2 = ok(T2) },
{ R = ok(T1 - T2) }
;
{ R2 = eof },
{ R = eof }
;
{ R2 = error(E) },
{ R = error(E) }
)
;
{ R1 = eof },
{ R = eof }
;
{ R1 = error(E) },
{ R = error(E) }
)
).
Example of usage:
% Write out the first 3 lines of stdin in reverse order.
main -->
call(
io__read_line_as_string `then`
io__read_line_as_string `then`
io__read_line_as_string,
Res
),
(
{ Res = ok(Line1 - Line2 - Line3) },
io__write_string(Line3),
io__write_string(Line2),
io__write_string(Line1)
;
{ Res = eof }
;
{ Res = error(Err) },
print(Err), nl.
).
Another variant, which reminds me of '>>=' in Haskell:
:- func seq(pred(io__result(T1), io__state, io__state),
pred(T1, io__result(T2), io__state, io__state)) =
pred(io__result(T2), io__state, io__state).
:- mode seq(pred(out, di, uo) is det, pred(in, out, di, uo) is det) =
out(pred(out, di, uo) is det) is det.
P1 `seq` P2 =
( pred(R::out, di, uo) is det -->
P1(R1),
(
{ R1 = ok(V) },
P2(V, R)
;
{ R1 = eof },
{ R = eof }
;
{ R1 = error(E) },
{ R = error(E) }
)
).
--
David Overton Department of Computer Science & Software Engineering
PhD Student The University of Melbourne, Victoria 3010, Australia
+61 3 8344 9159 http://www.cs.mu.oz.au/~dmo
--------------------------------------------------------------------------
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