Reginald Meeson <[EMAIL PROTECTED]> asks:

| This issue isn't really one of language definition, though.  It seems
| to me it's an issue for programming support environments.  I don't
| know of any language standard that includes requirements for
| debugging tools.  Any implementers willing to give this a whirl?

As a matter of fact, Gofer has a (fully polymorphic) function
                    show' :: a -> String
that can be used to obtain printable representations of functions.
It's used mainly at the top-level of the evaluator; only Strings
and Dialogues can actually be handled directly, so if you enter a
value with some other type, for example, an integer, then show'
is automatically applied to obtain a string representation.

Actually, show' is even more impure because it can sometimes
recover after hitting bottom.  For example:

   ? (3/0, 12)
   ({primDivInt 3 0},12)

Printing functions and printing bottom like this do seem to be quite
useful for debugging purposes, although they can also cause a little
confusion if you don't realize what's going on.

If uses of show' were restricted to the top-level, then the problems
that it could cause would be very limited, rather like the comments
somebody made about having a ShowFun request.

However, partly because Gofer doesn't have derived instances, and partly
because I wanted to make performance comparisons between overloaded and
non-overloaded implementations of show (BTW, the overloaded versions
were faster :-), the Gofer standard prelude also provides access to show'.
But I would caution very strongly against using the strings that it produces
to try and infer things about the original function.  As others have already
said -- that's a fast route to big problems.

If you really want to manipulate some concrete representation of function
values, the best thing to do is to create an explicit concrete
representation.  As a simple example, some functions of type Int -> Int
can be represented using:

> data FunctionOfN = N | Const Int | Sum FunctionOfN FunctionOfN

It's easy to manipulate these things in certain ways:

> constFold (Sum a b) = case (constFold a, constFold b) of
>                         (Const u,  Const v) -> Const (u+v)
>                         (a',       b')      -> Sum a' b'
> constFold other     = other

For example:

    ? constFold (Sum (Sum N (Const 1)) (Sum (Const 3) (Const 4)))
    Sum (Sum N (Const 1)) (Const 7)

In a similar way, you can print, read and store these representations in a
standard, portable manner.

Now if you want the functions themselves, not their representations, then
you just write a simple `interpreter':

> interp          :: FunctionOfN -> (Int -> Int)
> interp N         = \n -> n
> interp (Const m) = \n -> m
> interp (Sum x y) = \n -> interp x n + interp y n

For example:

    ? interp (Sum (Sum N N) (Const 1))
    v136 (Sum N N) (Const 1)
    ? interp (Sum (Sum N N) (Const 1)) 12
    25

(Thought I'd include the first one as an example of show'ing a function).

Mark

Reply via email to