(* Delphin source code for (dependent) Delphin chapter * by Adam Poswolsky *) (* Natural Numbers (Example 2.1.1) *) sig %name N n nat>; (* Untyped $\lambda$-expressions using HOAS (Example 2.1.2) *) sig %name E x exp) -> exp> exp -> exp>; (* Formulas (Example 2.2.2) *) sig %name A o -> o> %infix right 10

(* base type... we could also represent them as LF variables *) ; (* Natural Deduction (Example 2.2.3) *) sig type> %name D d nd B) -> nd (A ar B)> nd A -> nd B> ; (* Typed Combinators (AKA Hilbert-Style Calculus) (Example 2.2.4) *) sig type> %name H h comb A -> comb B> ; (* Well-formed untyped $\lambda$-expressions a la de Bruijn (Example 2.2.5) *) (* an expression of type "variable N" is a number representing 1 to N *) sig type> %name X variable (s N)> ; (* Expressions (indexed by size of context) *) sig type> %name T t term P> term P> term P -> term P> ; (* Equality relation (Example 2.2.6) *) sig term P -> type> equiv (s P) E (var' (succ X))> (* eqVar is saying: * if E is the Xth variable when the context has size P, * then E is also the (X+1)st variable in the same context * extended with one element. *) equiv (s P) (E x) T) -> equiv P (lam [x] E x) (lam' T)> equiv P E2 T2 -> equiv P (app E1 E2) (app' T1 T2)>; (* Simple identity function *) params = , , , ; fun id : -> -> = fn => fn => ; (* First (BAD) attempt at recursive identity function (Example 4.1.1) *) (* Causes Match Non-Exhaustive Warnings on inner functions * as well as Termination Warnings since the order is set * defaultly to the order of the explicit arguments, but * we want the order to only be on the second argument. * (Solution is to make the first argument implicit.) *) params = , , , ; fun id1 : -> -> = fn => (fn => (case {} id1 of {} => ) ) | => (fn => let val = id1 val = id1 in end) | => fn => ; (* Good (fully explicit) recursive identity function (Example 4.1.2) * Causes Termination Warnings since the order is set * defaultly to the order of the explicit arguments, but * we want the order to only be on the second argument. * (Solution is to make the first argument implicit.) *) params = , , , ; fun id2 : ( and ) -> = fn ( and ) => (case {} id2 ( and ) of {} => ) | ( and ) => let val = id2 ( and ) val = id2 ( and ) in end | ( and ) => ; (* Final recursive identity function utilizing implicit types (Example 4.1.3) *) params = , , , ; fun id3 : -> = fn => (case {} id3 of {} => ) | => let val = id3 val = id3 in end | => ; (* Combinators to natural deduction derivations (Example 4.5.1 and 5.4.1) *) params = . ; fun hil2nd : -> = fn => | => | => let val = hil2nd

val = hil2nd

in end; (* Bracket Abstraction (Example 4.5.2 and 5.4.2) *) params = , , , ; fun ba : comb B> -> = fn <[x] x> => | <[x] MP (H1 x) (H2 x)> => let val = ba <[x] H1 x> val = ba <[x] H2 x> in end | <[x] H> => ; type ndParamFun = ( -> ) (* Natural deduction derivations to Combinators (Example 4.5.3 and 5.4.3) *) params = , , , ; fun nd2hil : ndParamFun -> -> = fn W => fn => (case ({}{} nd2hil (W with => ) ) of ({}{} ) => ba <[h] H h>) | => let val

= nd2hil W val

= nd2hil W in end | => W ; (* Sample execution (Example 4.5.4 and 5.4.4) *) val test-nd2hil = nd2hil (fn .) ; (* OUTPUT: * val test-nd2hil : * = *) (* HOAS to de Bruijn (Example 4.6.1 and 5.4.5) *) (* We comment out the first argument because it is inferable * and we do not want it in the termination order *) params = , , , ; fun toDebruijn : (* -> *) ( -> * ) -> -> * = (* fn

=> *) fn W => (fn => let val W' : -> * = fn => let val (,) = W in (, ) end in case ({}{} toDebruijn (* *) (W' with => (,)) ) of {}{}(, ) => (, ) end | => let val (,) = toDebruijn (*

*) W val (,) = toDebruijn (*

*) W in (, ) end | => let val (, ) = W in (, ) end); (* de Bruijn to HOAS (Example 4.6.2 and 5.4.6) *) (* We comment out the first argument because it is inferable * and we do not want it in the termination order *) params = , , , ; fun toHOAS : (* -> *) ( -> * ) -> -> * = (* fn

=> *) fn W => (fn => (case ({}{} toHOAS (* *) ((fn {}{} ( => (, )) | {}{} ( => (let val (, ) = W in {}{} (, ) end) \x \d) ) \x \d) ) of {}{} (, ) => (, )) | => let val (,) = toHOAS (*

*) W val (,) = toHOAS (*

*) W in (, ) end | => W ); (* Sample conversions (Example 4.6.3) *) val test1 : ( * _) = toDebruijn (* *) (fn .) ; (* OUTPUT: * val test1 : * * = , * *) val test2 = let val (,<_>) = test1 val (,<_>) = toHOAS (* *) (fn .) in end; (* OUTPUT: * val test2 : * = *)