| 96 |      1 | <HTML>
 | 
|  |      2 | <HEAD>
 | 
|  |      3 |    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
 | 
|  |      4 |    <TITLE>G4ip</TITLE>
 | 
|  |      5 | </HEAD>
 | 
|  |      6 | <BODY TEXT="#000000" BGCOLOR="#C7C3C7" LINK="#0000EF" VLINK="#51188E" ALINK="#FF0000">
 | 
|  |      7 | 
 | 
|  |      8 | <H2>An Implementation of G4ip in Pizza</H2>
 | 
|  |      9 | 
 | 
|  |     10 | <FONT COLOR="#800000"><B>Warning:</B></FONT> 
 | 
|  |     11 | This page is now rather old! While you might still be interested
 | 
|  |     12 | in the algorithms, Robert Macdonald reported that Pizza and the current Java 
 | 
|  |     13 | implementation (version 1.3.0) do not work together. This means you need to 
 | 
|  |     14 | install an older Java version if you want to recompile the files given below. 
 | 
|  |     15 | I am happy to answer all question concerning the prover, but be aware that 
 | 
|  |     16 | currently for any kind of Java stuff I am using MLJ, which as of writing 
 | 
|  |     17 | this note  has not yet been made available for the general audience (maybe
 | 
|  |     18 | in the future also its OCaml equivalent). So I am not very fluent in Pizza
 | 
|  |     19 | anymore. <B>Update</B> Pizza development is continued and starting from version 
 | 
|  |     20 | <A HREF="http://pizzacompiler.sourceforge.net/">0.40</A> it should work
 | 
|  |     21 | with recent Java implementations.<P> 
 | 
|  |     22 | 
 | 
|  |     23 | 
 | 
|  |     24 | Jump to the <A HREF="#Implementation">implementation.</a>
 | 
|  |     25 | 
 | 
|  |     26 | 
 | 
|  |     27 | <H4>Introduction</H4>
 | 
|  |     28 | 
 | 
|  |     29 | 
 | 
|  |     30 | A convenient representation of intuitionistic logic is Getzen's 
 | 
|  |     31 | sequent calculus LJ (also G1i). A sequent of LJ can be proved 
 | 
|  |     32 | by applying inference rules until one reaches axioms, or can make no further 
 | 
|  |     33 | progress in which case one must backtrack or even abandon the search. 
 | 
|  |     34 | Unfortunately an interpreter for LJ using this depth-first strategy cannot 
 | 
|  |     35 | guarantee termination of the proof search.  Several modifications can be 
 | 
|  |     36 | made to LJ's inference rules without loss of soundness and completeness.  
 | 
|  |     37 | As result an efficient depth-first proof search can be designed for the 
 | 
|  |     38 | propositional fragment of intuitionistic logic. The name G4ip has been 
 | 
|  |     39 | assigned to the corresponding calculus in 
 | 
|  |     40 | <A HREF="#TroelstraSchwichtenberg96">[Troelstra and Schwichtenberg, 1996]</a>. 
 | 
|  |     41 | This calculus is also known as LJT which has been studied thoroughly 
 | 
|  |     42 | in <A HREF="#Dyckhoff92">[Dyckhoff, 1992]</a>. The inference rules of 
 | 
|  |     43 | G4ip are given <A HREF="G4ip.html">here</A>.<P>
 | 
|  |     44 | 
 | 
|  |     45 | It is not very complicated to implement an interpreter for G4ip using a logic 
 | 
|  |     46 | programming language (backtracking is directly supported within the language).
 | 
|  |     47 | Our first implementation is written in the logic programming language
 | 
|  |     48 | <A HREF="http://www.cis.upenn.edu/~dale/lProlog/terzo/index.html">Lambda Prolog</A> 
 | 
|  |     49 | and can be found <A HREF="G4ip.mod">here</A>. Another implementation by
 | 
|  |     50 | Hodas and Miller written in <A HREF="http://www.cs.hmc.edu/~hodas/research/lolli/">Lolli</a>
 | 
|  |     51 | can be found <A HREF="ftp://ftp.cse.psu.edu/pub/dale/ic94-code/index.html">here</A>
 | 
|  |     52 | (see <A HREF="#HodasMiller94">[Hodas and Miller, 1994]</a>). These are simple and 
 | 
|  |     53 | straightforward implementations of G4ip's rules. On the other hand it seems 
 | 
|  |     54 | that imperative languages need a rather high overhead of code when implementing
 | 
|  |     55 | a logic calculus. For example choice points are usually implemented with stacks.
 | 
|  |     56 | We shall demonstrate the implementation technique of success 
 | 
|  |     57 | continuations which provides an equally simple method for implementing logic calculi 
 | 
|  |     58 | in imperative languages. This technique is not new: it has been introduced in 
 | 
|  |     59 | <A HREF="#Carlsson84">[Carlsson, 1984]</a>. This paper presents a rather technical
 | 
|  |     60 | implementation of Prolog in LISP. Later an excellent paper, 
 | 
|  |     61 | <A HREF="#ElliotPfenning91">[Elliot and Pfenning, 1991]</a>, appeared which 
 | 
|  |     62 | describes a full-fledged implementation of Lambda Prolog in SML.
 | 
|  |     63 | We demonstrate the technique of success continuations for G4ip in 
 | 
|  |     64 | <A HREF="http://www.cis.unisa.edu.au/~pizza/">Pizza</A>.<P>
 | 
|  |     65 | 
 | 
|  |     66 | Pizza is an object-oriented programming language and an attractive extension of  
 | 
|  |     67 | <A HREF="http://www.javasoft.com/">Java</A>. Although Pizza is a superset of
 | 
|  |     68 | Java, Pizza programs can be translated into Java or compiled into ordinary
 | 
|  |     69 | Java Byte Code (see <A HREF="#OderskyWadler97">[Odersky and Wadler, 1997]</a>
 | 
|  |     70 | for a technical introduction to Pizza). We make use of the following two new 
 | 
|  |     71 | features of Pizza:
 | 
|  |     72 | <UL>
 | 
|  |     73 | <LI> higher-order functions, i.e. functions may be passed as parameters or returned
 | 
|  |     74 | from methods,
 | 
|  |     75 | <LI> class cases and pattern matching: this allows much simpler and more readable code.
 | 
|  |     76 | </UL>
 | 
|  |     77 | 
 | 
|  |     78 | These features are not directly present in Java, but Pizza makes them accessible by 
 | 
|  |     79 | translating them into Java. Pizza provides the programmer with the same 
 | 
|  |     80 | extensive libraries for graphic and network applications as Java. The higher-order 
 | 
|  |     81 | functions are essential for the technique of success continuations. The success 
 | 
|  |     82 | continuations are functions passed as parameters or returned as values.<BR>
 | 
|  |     83 | 
 | 
|  |     84 | 
 | 
|  |     85 | <H4>The Representation of Formulae and Sequents</H4>
 | 
|  |     86 | 
 | 
|  |     87 | Amongst the new language features of Pizza are class cases and pattern
 | 
|  |     88 | matching, which provide a very pleasant syntax for algebraic data types. The
 | 
|  |     89 | formulae of G4ip are specified by the following grammar:<P>
 | 
|  |     90 | 
 | 
|  |     91 | <CODE>F ::= false | A | F & F | F v F | F -> F</CODE><P>
 | 
|  |     92 | 
 | 
|  |     93 | 
 | 
|  |     94 | The class cases allow a straightforward implementation of this specification;
 | 
|  |     95 | it is analogous to the SML implementation of 
 | 
|  |     96 | <A HREF="http://www.cis.upenn.edu/~dale/lProlog/terzo/index.html">Lambda Prolog's</A> 
 | 
|  |     97 | formulae in <A HREF="#ElliotPfenning91">[Elliot and Pfenning, 1991]</A>. The class 
 | 
|  |     98 | of formulae for G4ip is given below:<P>
 | 
|  |     99 | 
 | 
|  |    100 | <TT>
 | 
|  |    101 | <DL>
 | 
|  |    102 | <DD>public class Form {            </DD>
 | 
|  |    103 | <DD>      case False();              </DD>    
 | 
|  |    104 | <DD>      case Atm(String c);        </DD>  
 | 
|  |    105 | <DD>      case And(Form c1,Form c2); </DD>
 | 
|  |    106 | <DD>      case Or(Form c1,Form c2);  </DD>
 | 
|  |    107 | <DD>      case Imp(Form c1,Form c2); </DD>
 | 
|  |    108 | <DD>}                              </DD>
 | 
|  |    109 | </DL>
 | 
|  |    110 | </TT>
 | 
|  |    111 | 
 | 
|  |    112 | Two examples that illustrate the use of the representation are as follows:<P>
 | 
|  |    113 | 
 | 
|  |    114 | 
 | 
|  |    115 | <CODE>          p -> p  </CODE> 
 | 
|  |    116 | is represented as   <CODE>   Imp(Atm("p"),Atm("p"))</CODE><BR>
 | 
|  |    117 | <CODE>a v (a -> false)  </CODE> is represented as  <CODE>   Or(Atm("a"),Imp(Atm("a"),False()))</CODE><P>
 | 
|  |    118 | 
 | 
|  |    119 | The class cases of Pizza also support an implementation of formulae specified
 | 
|  |    120 | by a mutually recursive grammar.  This is required, for example, when
 | 
|  |    121 | implementing hereditary Harrop formulae.<P> 
 | 
|  |    122 | 
 | 
|  |    123 | The sequents of G4ip, which have the form <CODE>Gamma=>G</CODE>, are represented
 | 
|  |    124 | by means of the class below. The left-hand side of each sequent is specified by a multiset 
 | 
|  |    125 | of formulae.  Therefore, we do not need to worry about the order in which the
 | 
|  |    126 | formulae occur.<P>
 | 
|  |    127 | 
 | 
|  |    128 | <TT>
 | 
|  |    129 | <DL>
 | 
|  |    130 | <DD>public class Sequent  {                       </DD>
 | 
|  |    131 | <DD>   Form  G;                                      </DD>         
 | 
|  |    132 | <DD>   Context Gamma;                                </DD>
 | 
|  |    133 | <DD>   public Sequent(Context _Gamma, Form _G) {...};</DD>
 | 
|  |    134 | <DD>}                                             </DD>
 | 
|  |    135 | </DL>
 | 
|  |    136 | </TT>
 | 
|  |    137 | 
 | 
|  |    138 | We have a constructor for generating new sequents during proof search. 
 | 
|  |    139 | <CODE>Context</CODE> is a class which represents multisets; it is a simple 
 | 
|  |    140 | extension of the class <CODe>Vector</CODE> available in the Java libraries. 
 | 
|  |    141 | This class provides methods for adding elements to a multiset (<CODE>add</CODE>), 
 | 
|  |    142 | taking out elements from a multiset (<CODE>removeElement</CODE>) and testing
 | 
|  |    143 | the membership of an element in a multiset (<CODE>includes</CODE>).
 | 
|  |    144 | 
 | 
|  |    145 | 
 | 
|  |    146 | <H4>The Technique of Success Continuations</H4>
 | 
|  |    147 | 
 | 
|  |    148 | We have to distinguish between the concepts of proof obligations (which must 
 | 
|  |    149 | be proved) and choice points (which can be tried out to construct a proof). 
 | 
|  |    150 | The first argument of the method <CODE>prove</CODE> is the sequent being 
 | 
|  |    151 | proved; the second argument is an anonymous function. The function <CODE>prove</CODE> is now 
 | 
|  |    152 | of the form <CODE>prove(sequent,sc)</CODE>.  Somewhat simplified the
 | 
|  |    153 | first argument is the leftmost premise and the second argument <CODE>sc</CODE>, 
 | 
|  |    154 | the success continuation, represents the other proof obligations. In case we
 | 
|  |    155 | succeed in proving the first premise we then can attempt to prove the other
 | 
|  |    156 | premises. The technique of success continuations will be explained using the following 
 | 
|  |    157 | proof (each sequent is marked with a number):<P>
 | 
|  |    158 | 
 | 
|  |    159 | <UL><img src="proof.gif" width=337 height=112></UL>
 | 
|  |    160 | <BR><P>
 | 
|  |    161 | 
 | 
|  |    162 | The inference rules fall into three groups:
 | 
|  |    163 | 
 | 
|  |    164 | <UL>
 | 
|  |    165 | <LI>  inference rules with a single premise (e.g. ->_R, &_L), 
 | 
|  |    166 | <LI>  inference rules with two premises (e.g. v_L) and
 | 
|  |    167 | <LI>  inference rules without premises (e.g. Axiom). 
 | 
|  |    168 | </UL>
 | 
|  |    169 | 
 | 
|  |    170 | The following picture shows the order in which the sequents are being proved.
 | 
|  |    171 | 
 | 
|  |    172 | <UL><img src="execution.gif" width=358 height=191></UL>
 | 
|  |    173 | <BR><P>
 | 
|  |    174 | 
 | 
|  |    175 | Suppose we have called <CODE>prove</CODE> with a sequent <B>s</B> and a 
 | 
|  |    176 | success continuation <B>is</B>. The inference rules of the first
 | 
|  |    177 | group manipulate  <B>s</B> obtaining <B>s'</B> and call <CODE>prove</CODE> 
 | 
|  |    178 | again with the new sequent <B>s'</B> and the current success continuation 
 | 
|  |    179 | (Steps 1-2, 3-4 and 5-6).  The inference rules 
 | 
|  |    180 | of the second group have two premises, <B>s1</B> and <B>s2</B>. 
 | 
|  |    181 | These rules call <CODE>prove</CODE> with <B>s1</B> and a new success 
 | 
|  |    182 | continuation <CODE>prove(s2,is)</CODE> (Step 2-3).
 | 
|  |    183 | The third group of inference rules only invoke the success continuation 
 | 
|  |    184 | if the rule was applicable (Steps 4-5 and 6-7).<P>
 | 
|  |    185 | 
 | 
|  |    186 | 
 | 
|  |    187 | We are going to give a detailed description of the code for the rules: &_L,
 | 
|  |    188 | ->_R, v_Ri, v_L and Axiom.  The function <CODE>prove</CODE> receives as arguments 
 | 
|  |    189 | a sequent <CODE>Sequent(Gamma,G)</CODE> and a success continuation 
 | 
|  |    190 | <CODE>sc</CODE>.  It enumerates all formulae as being principal and 
 | 
|  |    191 | two switch statements select a corresponding case depending on the form 
 | 
|  |    192 | and the occurrence of the principal formula.<P> 
 | 
|  |    193 | 
 | 
|  |    194 | The &_L rule is in the first group; it modifies the sequent being proved and calls
 | 
|  |    195 | <CODE>prove</CODE> again with the current success continuation sc. The code is as
 | 
|  |    196 | follows (<CODE>Gamma</CODE> stands for the set of formulae on the left-hand
 | 
|  |    197 | side of a sequent excluding the principal formula; <CODE>G</CODE> stands 
 | 
|  |    198 | for the goal formula of a sequent; <CODE>B</CODE> and <CODE>C</CODE> stand 
 | 
|  |    199 | for the two components of the principal formula).<P>
 | 
|  |    200 | 
 | 
|  |    201 | <TT>
 | 
|  |    202 | <DL>
 | 
|  |    203 | <DD>case And(Form B, Form C):</DD>
 | 
|  |    204 | <DD>   prove(new Sequent(Gamma.add(B,C),G),sc); break;</DD>
 | 
|  |    205 | </DL>
 | 
|  |    206 | </TT>
 | 
|  |    207 | 
 | 
|  |    208 | The code for the ->_R rule is similar:<P>
 | 
|  |    209 | 
 | 
|  |    210 | <TT>
 | 
|  |    211 | <DL>
 | 
|  |    212 | <DD>case Imp(Form B, Form C):</DD>
 | 
|  |    213 | <DD>   prove(new Sequent(Gamma.add(A),B),sc); break;</DD>
 | 
|  |    214 | </DL>
 | 
|  |    215 | </TT>
 | 
|  |    216 | 
 | 
|  |    217 | The v_Ri rule is an exception in the first group. It breaks up a goal
 | 
|  |    218 | formula of the form <CODE>B1 v B2</CODE> and proceeds with one of its component. 
 | 
|  |    219 | Since we do not know in advance which component leads to a successful proof we have
 | 
|  |    220 | to try both. Therefore this rule acts as a choice point, which is encoded by a
 | 
|  |    221 | recursive call of <CODE>prove</CODE> for each case.
 | 
|  |    222 | 
 | 
|  |    223 | <TT>
 | 
|  |    224 | <DL>
 | 
|  |    225 | <DD>case Or(Form B1,Form B2):</DD>
 | 
|  |    226 | <DD>   prove(new Sequent(Gamma,B1),sc);</DD>
 | 
|  |    227 | <DD>   prove(new Sequent(Gamma,B2),sc); break;</DD>
 | 
|  |    228 | </DL>
 | 
|  |    229 | </TT>
 | 
|  |    230 | 
 | 
|  |    231 | The v_L rule falls into the second group where the current success
 | 
|  |    232 | continuation, sc, is modified. It calls <CODE>prove</CODE> with the first premise,
 | 
|  |    233 | <CODE>B,Gamma=>G</CODE>, and wraps up the success continuation with the 
 | 
|  |    234 | new proof obligation, <CODE>C,Gamma=>G</CODE>. The construction 
 | 
|  |    235 | <CODE>fun()->void {...}</CODE> defines an anonymous function: the new 
 | 
|  |    236 | success continuation. In case the sequent <CODE>B,Gamma=>G</CODE> can be 
 | 
|  |    237 | proved, this function is invoked.
 | 
|  |    238 | 
 | 
|  |    239 | <TT>
 | 
|  |    240 | <DL>
 | 
|  |    241 | <DD>case Or(Form B,Form C):</DD>
 | 
|  |    242 | <DD>   prove(new Sequent(Gamma.add(B),G),</DD>
 | 
|  |    243 | <DD>           
 | 
|  |    244 |       fun()->void {prove(new Sequent(Gamma.add(C),G),sc);}</DD>
 | 
|  |    245 | <DD>        ); break</DD>
 | 
|  |    246 | </DL>
 | 
|  |    247 | </TT>
 | 
|  |    248 | 
 | 
|  |    249 | The Axiom rule falls into the third group. It first checks if the
 | 
|  |    250 | principal formula (which is an atom) matches with the goal formula and
 | 
|  |    251 | then invokes the success continuation sc in order to prove all remaining
 | 
|  |    252 | proof obligations.
 | 
|  |    253 | 
 | 
|  |    254 | <TT>
 | 
|  |    255 | <DL>
 | 
|  |    256 | <DD>case Atm(String c):</DD>
 | 
|  |    257 | <DD>   if (G instanceof Atm) { </DD>
 | 
|  |    258 | <DD>      if (G.c.compareTo(c) == 0) { sc(); }</DD>
 | 
|  |    259 | <DD>   } break;</DD>
 | 
|  |    260 | </DL>
 | 
|  |    261 | </TT>
 | 
|  |    262 | 
 | 
|  |    263 | The proof search is started with an initial success continuation <B>is</B>. 
 | 
|  |    264 | This initial success continuation is invoked when a proof has been found. 
 | 
|  |    265 | In this case we want to give some response to the user, an
 | 
|  |    266 | example for the initial success continuation could be as follows:
 | 
|  |    267 | 
 | 
|  |    268 | <TT>
 | 
|  |    269 | <DL>
 | 
|  |    270 | <DD> public void initial_sc()  { System.out.println("Provable!"); } </DD>
 | 
|  |    271 | </DL>
 | 
|  |    272 | </TT>
 | 
|  |    273 | 
 | 
|  |    274 | 
 | 
|  |    275 | Suppose we attempt to start the proof search with <CODE>prove(p,p => p,is)</CODE>. 
 | 
|  |    276 | We would find that the prover responds twice with <CODE>"Provable!"</CODE>, because 
 | 
|  |    277 | it finds two proofs. In our implementation this problem is avoided by encoding 
 | 
|  |    278 | the proof search as a thread. Whenever a proof is found, the initial success 
 | 
|  |    279 | continuation displays the proof and suspends the thread. The user can 
 | 
|  |    280 | decide to resume with the proof search or abandon the search.
 | 
|  |    281 | 
 | 
|  |    282 | 
 | 
|  |    283 | <H4>Conclusion</H4>
 | 
|  |    284 | 
 | 
|  |    285 | The implementation cannot be considered as optimal in terms of speed. 
 | 
|  |    286 | A much more efficient algorithm for G4ip (but less clear) has been 
 | 
|  |    287 | implemented by Dyckhoff in Prolog. Similar ideas can be encoded in our 
 | 
|  |    288 | Pizza implementation; but our point was not the efficiency but the clarity 
 | 
|  |    289 | of the implementation using success continuations.
 | 
|  |    290 | The technique is applicable elsewhere whenever backtracking is required.  We
 | 
|  |    291 | compared the code of our implementation with an implementation in
 | 
|  |    292 | <A HREF="http://www.cis.upenn.edu/~dale/lProlog/terzo/index.html">Lambda Prolog</A>: 
 | 
|  |    293 | the ratio of code is approximately 2 to 1. 
 | 
|  |    294 | (see <A HREF="G4ip.mod">LambdaProlog code</A> and 
 | 
|  |    295 | <A HREF="minimal/MinProver.pizza">Pizza code</A>).
 | 
|  |    296 | This result is partly due to the fact that we had to implement a class for 
 | 
|  |    297 | multisets. In a future version of Java, we could have accessed a package 
 | 
|  |    298 | in the library. The technique of success continuation can also be applied 
 | 
|  |    299 | to a first-order calculus as shown in <A HREF="#ElliotPfenning91">[Elliot and Pfenning, 1991]</a>, 
 | 
|  |    300 | but the required mechanism of substitution needs to be implemented separately. 
 | 
|  |    301 | However, we think the technique of success continuations provides a remarkable 
 | 
|  |    302 | simple implementation for logic calculi.<P> 
 | 
|  |    303 | 
 | 
|  |    304 | We had to make some compromises in order to support as many platforms
 | 
|  |    305 | as possible. This should change with the release of new browsers and a stable
 | 
|  |    306 | Java-specification (resp. Pizza-specification).<P> 
 | 
|  |    307 | 
 | 
|  |    308 | A paper about the implementation appeared in the LNAI series No 1397,
 | 
|  |    309 | Automated Reasoning with Analytic Tableaux and Related Methods, 
 | 
|  |    310 | ed. Harry de Swart, International Conference Tableaux'98 in Oisterwijk, 
 | 
|  |    311 | The Netherlands. The title is: Implementation of Proof Search in 
 | 
|  |    312 | the Imperative Programming Language Pizza (pp. 313-319). The paper can be 
 | 
|  |    313 | found here: <A HREF="Tableaux98.dvi.gz">DVI</A>, <A HREF="Tableaux98.ps.gz">Postscript</A> 
 | 
|  |    314 | (© Springer-Verlag <A HREF="http://www.springer.de/comp/lncs/index.html">LNCS</A>).<P>
 | 
|  |    315 | 
 | 
|  |    316 | 
 | 
|  |    317 | <B>Acknowledgements:</B> I am very grateful for Dr Roy Dyckhoff's constant
 | 
|  |    318 | encouragement and many comments on my work. I thank Dr Gavin Bierman who
 | 
|  |    319 | helped me to test the prover applet. 
 | 
|  |    320 | 
 | 
|  |    321 | <HR>
 | 
|  |    322 | <A NAME="Implementation"></A><H4>Implementation</H4>
 | 
|  |    323 | 
 | 
|  |    324 | <A HREF="README">Readme</A><p>
 | 
|  |    325 | 
 | 
|  |    326 | <A HREF="ProverApplet.html"><B>Prover Applet</B></A><BR>
 | 
|  |    327 | <A HREF="ProverAppletJar.html"><B>Jar Version</B></A> 
 | 
|  |    328 | (slightly faster, but requires Netscape 4 or MS Explorer 4).<P>
 | 
|  |    329 | 
 | 
|  |    330 | 
 | 
|  |    331 | <HR>
 | 
|  |    332 | <B>References</B> 
 | 
|  |    333 | <UL>
 | 
|  |    334 | <LI> <A NAME="Carlsson84"></A>
 | 
|  |    335 |      [Carlsson, 1984]<BR> 
 | 
|  |    336 |      M. Carlsson, On  Implementing Prolog in Functional Programming, 
 | 
|  |    337 |      New Generation Computing, pp 347-359.
 | 
|  |    338 | <LI> <A NAME="Dyckhoff92"></A>
 | 
|  |    339 |      [Dyckhoff, 1992]<BR> 
 | 
|  |    340 |      <A HREF="http://www-theory.dcs.st-and.ac.uk/~rd/">R. Dyckhoff</A>, 
 | 
|  |    341 |      Contraction-Free Sequent Calculi for Intuitionistic Logic, 
 | 
|  |    342 |      Journal of Symbolic Logic 57(3), pp 795-807.
 | 
|  |    343 | <LI> <A NAME="ElliotPfenning91"></A>
 | 
|  |    344 |      [Elliot and Pfenning, 1991]<BR> 
 | 
|  |    345 |      C. Elliot,
 | 
|  |    346 |      <A HREF="http://foxnet.cs.cmu.edu/people/fp/homepage.html">F. Pfenning</A>, 
 | 
|  |    347 |      A Semi-Functional Implementation of a Higher-Order Programming Language, 
 | 
|  |    348 |      In Peter Lee, editor, Topics in Advanced Language Implementation, MIT Press,
 | 
|  |    349 |      pp 289-352. 
 | 
|  |    350 |      <A HREF="http://www.cs.cmu.edu/~fp/papers/elpsml-paper.tar.gz">Available electronically</a>.
 | 
|  |    351 | <LI> <A NAME="HodasMiller94"></A>
 | 
|  |    352 |      [Hodas and Miller, 1994]<BR> 
 | 
|  |    353 |      <A HREF="http://www.cs.hmc.edu/~hodas/">J. Hodas</A>,
 | 
|  |    354 |      <A HREF="http://www.cse.psu.edu/~dale/">D. Miller</A>,
 | 
|  |    355 |      Logic Programming in a Fragment of Intuitionistic Linear Logic, 
 | 
|  |    356 |      Information and Computation 110(2), pp 327-365.
 | 
|  |    357 |      <A HREF="ftp://ftp.cse.psu.edu/pub/dale/ic94.ps.Z">Available electronically</a>.
 | 
|  |    358 | <LI> <A NAME="OderskyWadler97"></A>
 | 
|  |    359 |      [Odersky and Wadler, 1997]<BR> 
 | 
|  |    360 |      <A HREF="http://www.cis.unisa.edu.au/~cismxo">M. Odersky</A>,
 | 
|  |    361 |      <A HREF="http://cm.bell-labs.com/cm/cs/who/wadler/">P. Wadler</A>,
 | 
|  |    362 |      Pizza into Java: Translating Theory into Practice, 
 | 
|  |    363 |      In Proceedings of the 24th ACM Symposium on Principles of Programming Languages.
 | 
|  |    364 |      <A HREF="http://www.cis.unisa.edu.au/~cismxo/papers/popl97.dvi.gz">Available electronically</a>.
 | 
|  |    365 | <LI> <A NAME="TroelstraSchwichtenberg96"></A>
 | 
|  |    366 |      [Troelstra and Schwichtenberg, 1996]<BR>
 | 
|  |    367 |      <A HREF="http://turing.wins.uva.nl/~anne/">A. Troelstra</A>, 
 | 
|  |    368 |      <A HREF="http://www.mathematik.uni-muenchen.de/~gadmin6/professoren/schwichtenberg">H. Schwichtenberg</A>,  
 | 
|  |    369 |      Basic Proof Theory, Cambridge Tracts in Theoretical Computer Science,
 | 
|  |    370 |      Cambridge University Press.
 | 
|  |    371 | </UL>
 | 
|  |    372 | 
 | 
|  |    373 | 
 | 
|  |    374 | <HR>
 | 
|  |    375 | <ADDRESS>
 | 
|  |    376 | <A HREF="mailto:Christian.Urban@cl.cam.ac.uk">Christian Urban</A></ADDRESS>
 | 
|  |    377 | 
 | 
|  |    378 | 
 | 
|  |    379 | <P><!-- Created: Tue Mar  4 00:23:25 GMT 1997 -->
 | 
|  |    380 | <!-- hhmts start -->
 | 
|  |    381 | Last modified: Sun Sep 23 12:04:47 BST 2001
 | 
|  |    382 | <!-- hhmts end -->
 | 
|  |    383 | </BODY>
 | 
|  |    384 | </HTML>
 |