formatting, type classes, and existential types

Peter Schachte pets at students.cs.mu.OZ.AU
Wed Jul 1 11:52:59 AEST 1998


This is a follow-up to a discussion I had with Fergus and DJ yesterday, sent
to mercury-developers because I think the wider audience may be interested.

For a long time, I've believed that the "right" way to do formatted output
is with a predicate that takes a list of format specifiers:

  :- pred format(list(format_spec)::in, io_state::di, io_state::uo) is det.

A reasonable approximation of the definition of format_spec might be:

  :- type justification ---> left ; right ; center.
  :- type format_spec --->
	(   string(string)
	;   int(int)
	;   float(float)		% most concise output
	;   float(float,int)		% specifying digits of precision
	;   expfloat(float,int)		% same, but in exponential notation
	;   char(char)
	;   justified(format_spec, justification, int)
					% give field width and justification
	).

This isn't quite what I wanted, because I find the string/1, int/1, float/1,
and char/1 wrappers ugly and overly verbose.  But I can live with them if I
have to.

This could be implemented in Mercury with no problems.  Unfortunately, it's
pretty inflexible.  You'd really like to allow users to define their own
format specifiers. 

The standard Prolog solution to this problem would be to have a hook
predicate, which would be declared multifile, to translate a format_spec
into a string.  format/3 would invoke this for each format spec, and then
print the result.  No problem. 

But Mercury's type system won't allow this, as you'd need to have a type
definition split over multiple files.  Mercury's module system won't allow
it either, as you'd need to have a predicate split over multiple files, too. 

When I've mentioned this problem in the past to Mercurians, the answer has
always been that type classes will allow this.  You just make format_spec be
a type class that requires a format_spec_to_string operation, and Bob's your
uncle. 

Unfortunately, now the list argument to format would be a list of things in
a type class, rather than things in a type, so Bob's not your uncle after
all.  The list is actually heterogeneous, and therefore, I was given to
understand, this requires existential types, and then Bob will be your uncle
again.

Now that existential types are (just about) there, I'd like to see how this
problem can be handled.  What will the person writing the formatting package
have to write to define the built-in formatting code suggested above?  And
what will, say, the implementor of a bignum package have to write to provide
an implementation of format_spec_to_string for bignums?  Finally, what are
the prospects for having a version of format/3 which doesn't require you to
wrap everything?  I'd much rather write (this is in a DCG clause):

	format(["The answer is ", N, ".\n"])

than this:

	format([string("The answer is "), int(N), string(".\n")])


-Peter Schachte               | Men occasionally stumble over the truth, but
mailto:pets at cs.mu.OZ.AU       | most of them pick themselves up and hurry
http://www.cs.mu.oz.au/~pets/ | off as if nothing ever happened.
PGP: finger pets at 128.250.37.3 |     -- Winston Churchill (1874-1965) 




More information about the developers mailing list