[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