a universal printer for Haskell?

Bernard James POPE bjpop@cs.mu.OZ.AU
Tue, 19 Feb 2002 20:55:15 +1100 (EST)


Hi,

> >But you ought to be able to print the empty list,
> >without having to make some bogus type qualification (which
> >is in general not a solution to the problem of printing arbitrary values).
> 
> But how about the difference between
> show ([] :: [Int] ) == "[]"
> show ([] :: [Char]) == "\"\""
>
> You probably want the first, but I want the
> second in the cases I'm working with strings.

There is a reason why I want the first and not the second. Imagine a 
debugger for Haskell that prints values from computations, so that the user
can inspect what is happening. How is the debugger to present these values?
The danger of using user defined print mechanisms is that they might
have bugs in them. Okay so the user of the debugger can say: "I really really
trust my print mechanisms, so please use them". But there ought to be some
fallback strategy where the debugger can always print something which is 
meaningful. The most basic representation I can think of that would make any
sense is something derived directly from the definition of the type. Sure,
the abstraction boundary is broken, but sometimes you just might need to 
do that to debug your program.

There are also other uses for such canonical printing. Somtimes you want
to write out a data structure and read it back in again, and you want
to be sure that what you write will always be readable again. It is
quite an annoying maintenance problem when you have to keep the printer
and reader in sync. If such synchronisation can be handled by the compiler,
then all the better.

If you want something prettier, then you can always resort to the usual
techniques and put up with the odd unresolved overloading.

The basic problem with type classes for this is that there are too
many possible meanings for the one program, hence the example
with show []. Of course there should only be one meaning, which is why
I suggested making the printing mechanism defineable only by the
compiler.

You don't have to use the type class system to provide generic printing.
It could just be a primitive, Hugs has (or at least used to have) this.
Such a primitive is going to be a lot harder for something like the STG
machine however.

> It's not clear to me how much your proposal
> differs from extending the default meganism
> (http://www.haskell.org/onlinereport/decls.html#default-decls)
> to allow arbitrary classes, rather than only
> class Num, which would be more consistent
> with the current Haskell 98.

Perhaps you could extend defaulting to include classes outside the Num
hierarchy, but I suspect this is a minefield. 

I was hoping to avoid this by just making printing a special case, since 
at least I think it is quite useful. If we want to be really 
adventurous we might want to look at alternative overloading schemes that
do not suffer the same restrictions as type classes do. I think type classes
are here to stay, can we put up with more than one overloading mechanism
in Haskell, I don't know?

Cheers,
Bernie.