[stack] fundamental type system problems + possible solutions

John Nowak <[email protected]>
Newsgroups gmane.comp.lang.concatenative
Message-ID <[email protected]>
It seems there's a fundamental problem with typing concatenative  
languages: Most type systems are not compositional which destroys the  
simple algebra of concatenative programs. Take these equivalencies for  
example:

    [$A] i       ==  $A       -- application
    [$A] [$B] o  ==  [$A $B]  -- composition
    $a [$B] pa   ==  [$a $B]  -- partial application
    [$A] m       ==  [$A] $A  -- self-application

Unfortunately, all of these rules (except perhaps for partial  
application) fall apart once types are involved. This is of practical  
concern as it makes cut-and-paste refactoring impossible and will  
cause problems with many macro transformations.

What is needed is a type system that is compositional. One system that  
meets this requirement is System E developed by Carlier and Wells [1].  
While this seems like an appealing solution at first, the types  
produced by System E are so complex that they're not really human- 
decipherable. Even if a solution to making error reports  
understandable could be found via some form of type error slicing [2],  
there would still be no way to make types useful as documentation.

As I see it, there are three main benefits of static type systems:  
Automatic and correct documentation, increased safety, and increased  
efficiency. Of these three, I consider documentation to be the most  
important. After all, there are language implementations without  
static type systems that perform quite well such as SBCL and LuaJIT.  
As for safety, dynamic languages are used to build highly-reliable  
systems (see Erlang); ultimately, the design of a program and ability  
of the implementors contributes much more to software reliability than  
the presence of a type system (compare Haskell/Darcs to C/Perl/Git).

The need for documentation, however, you can't escape. This is  
especially so in stack-based languages where stack effect comments are  
necessary to make sense out of things. While no type system will  
replace the need for such comments entirely, as it is often necessary  
to state not just the type of a value but its purpose, a type system  
can at least ensure the correct number of arguments will always be  
passed and that type constraints will be respected.

I would rather have no type system than one which makes simple  
transformations, and hence macros and much refactoring, impossible.  
Static type systems seem doomed to being either non-compositional or  
not suited to producing human-readable documentation.  Therefore, as I  
see it, there are two possibilities going forward.

One is to develop a soft type system that hopefully will be able to  
report most errors without rejecting any program. If a language is  
designed with a soft type system in mind, the quality of error  
reporting can be quite good. For example, dynamic checks can be  
inserted to ensure lists are used homogeneously and type declarations  
can be required for data types to avoid the need for equi-recursive  
types.

The other approach would be some way of inferring the equivalences  
mentioned at the beginning of this email. I guess this would take the  
form of some kind of abstract interpretation. The goal here would not  
be to catch all type errors (although some would be catchable), but  
rather to provide a detailed description of what a function does  
beyond what an HM-based type system would be capable of yielding. It  
seems the primary issue here would be giving equivalencies for  
functions involving recursive data types. For example, if we define  
some 'each' function that simply places an element from a list on the  
stack and then calls some function repeatedly until the list is empty,  
how would we express this?

Anyway, these are just my current thoughts. As for Fifth, I've decided  
to delay inclusion of the type system until I can find a solution that  
won't cause problems with macros or inhibit cut-and-paste refactoring.  
(I'll credit Slava Pestov for reminding me of how critical this is.)  
Any thoughts would be appreciated, especially regarding the second  
approach described above.

- John

[1] http://www.church-project.org/modular/compositional/system-E/
[2] http://www.macs.hw.ac.uk/ultra/compositional-analysis/type-error-slicing/slicing.cgi
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.