<<

Resources: Some of the slides of this lecture were derived from [Järvi], with permission of the original author, by copy x = 1 & paste or by selection, annotation, or rewording. [Järvi] is let x = 1 in ... in turn based on [Pierce] as the underlying textbook.

x(1).

!x(1) x.set(1)

Programming Paradigms and Formal Semantics

Implementing Lambda Calculi in Prolog

Ralf Lämmel <1h [Järvi] Slides by J. Järvi: “Programming Languages”, CPSC 604 @ TAMU (2009) [Pierce] B.C. Pierce: Types and Programming Languages, MIT Press, 2002 Table of contents

• Untyped NB Objective: compare grammar- and rule-based formalization • Typed NB with the corresponding Prolog encodings / implementation. • Untyped

• Applied, untyped lambda calculus

• Applied, typed lambda calculus

© Ralf Lämmel, 2009-2011 unless noted otherwise 192 Untyped NB

© Ralf Lämmel, 2009-2011 unless noted otherwise 193 This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.

SyntaxMore than one syntactic of category NB Language NB t ::= terms: v value if t1 then t2 else t3 conditional succ t successor pred t predecessor iszero t test for zero

v ::= values: true constant true false constant false nv numeric value

nv ::= numeric values: 0 zero value succ nv successor value

© Ralf Lämmel, 2009-2011 unless noted otherwise 194 54 / 58 Prolog Syntax of NB term(V) :- value(V). term(if(T1,T2,T3)) :- term(T1), term(T2), term(T3). term(succ(T)) :- term(T). term(pred(T)) :- term(T). term(iszero(T)) :- term(T). We are faithful to the distinction of the value(true). syntactical categories. value(false). value(NV) :- nvalue(NV).

nvalue(zero). nvalue(succ(NV)) :- nvalue(NV).

© Ralf Lämmel, 2009-2011 unless noted otherwise 195 Prolog NB: sample terms

supposed to evaluate to 0

if(iszero(pred(succ(zero))),zero,succ(succ(zero))).

supposed to evaluate to false if(iszero(zero),iszero(succ(zero)),true).

© Ralf Lämmel, 2009-2011 unless noted otherwise 196 This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.

Typ es for EvaluationNB rules of NB Reminder evaluation rules NB (SOS) E-Iszero E-IszeroZero t t￿ → iszero 0 true iszero t iszero t￿ → → E-Succ E-Pred E-IszeroSucc t t￿ t t￿ iszero (succ nv) false → → → succ t succ t￿ pred t pred t￿ → → E-PredZero E-PredSucc E-IfTrue pred 0 0 pred (succ nv) nv if true then t else t t → → 2 3 → 2 E-IfFalse Exercise: what if false then t2 else t3 t3 → happens to our E-If t t￿ when we omit 1 → 1 if t then t else t if t￿ then t else t the rule? 1 2 3 → 1 2 3 14 / 28 © Ralf Lämmel, 2009-2011 unless noted otherwise 197 Prolog Evaluation rules of NB (SOS) % eval(pred(zero),zero). Disfavored eval(pred(succ(NV)),NV) :- nvalue(NV). semantics eval(succ(T1),succ(T2)) :- eval(T1,T2). eval(pred(T1),pred(T2)) :- eval(T1,T2). Note: appearances of eval(iszero(zero),true). metavariables in SOS eval(iszero(succ(NV)),false) :- nvalue(NV). translate into tests for values. eval(iszero(T1),iszero(T2)) :- eval(T1,T2). eval(if(true,T2,_),T2). eval(if(false,_,T3),T3). eval(if(T1,T2,T3),if(T4,T2,T3)) :- eval(T1,T4).

© Ralf Lämmel, 2009-2011 unless noted otherwise 198 Prolog Reflexive, transitive closure

manysteps(V,V) :- value(V). manysteps(T1,V) :- eval(T1,T2), manysteps(T2,V).

This is like ➝* in the formal setup, and the predicate works for any language with a binary reduction relation eval/2.

© Ralf Lämmel, 2009-2011 unless noted otherwise 199 Prolog Composing everything

:- [...]. % Import syntax and semantics :- [...]. % Import main predicate

:- current_prolog_flag(argv,Argv), ( append(_,['--',Input],Argv), main(Input), halt; true ).

Hence, we can invoke the language processor from the command-line prompt.

© Ralf Lämmel, 2009-2011 unless noted otherwise 200 Prolog

main(Input) :- see(Input), read(Term), seen, format('Input term: ~w~n',[Term]), manysteps(Term,X), show(X,Y), format('Value of term: ~w~n',[Y]).

show(zero,0) :- !. show(succ(X),Z) :- !, show(X,Y), Z is Y + 1. show(X,X).

© Ralf Lämmel, 2009-2011 unless noted otherwise 201 Running the NB interpreter

$ swipl -q -f main.pro -- ../samples/sample1.nb Input term: if(iszero(pred(succ(zero))),zero,succ(succ(zero))) Value of term: 0 $

© Ralf Lämmel, 2009-2011 unless noted otherwise 202 Typed NB

© Ralf Lämmel, 2009-2011 unless noted otherwise 203 This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU. Typ es for NB typing rules NB Types in NB

First, we need a few new syntactic forms T ::= types: Bool the Boolean type Nat the type of numeric values And typing rules:

T-If T-True T-False t1 : Bool t2 : Tt3 : T true : Bool false : Bool if t1 then t2 else t3 : T

T-Succ T-Pred T-Iszero © Ralf Lämmel, T-Zero2009-2011 unless noted otherwise 204 t : Nat t : Nat t : Nat 0 : Nat succ t : Nat pred t : Nat iszero t : Bool

15 / 28 Typ es for NB typing rules NB This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU. First, we need a few new syntactic forms T ::= types: Bool typingthe Boolean typerules NatNBthe type of numeric values And typing rules:

T-If T-True T-False t1 : Bool t2 : Tt3 : T true : Bool false : Bool if t1 then t2 else t3 : T

T-Succ T-Pred T-Iszero T-Zero t : Nat t : Nat t : Nat 0 : Nat succ t : Nat pred t : Nat iszero t : Bool

15 / 28

© Ralf Lämmel, 2009-2011 unless noted otherwise 205 Prolog NB typing rules

welltyped(true,bool). 1:1 mapping welltyped(false,bool). welltyped(zero,nat). welltyped(succ(T),nat) :- welltyped(T,nat). welltyped(pred(T),nat) :- welltyped(T,nat). welltyped(iszero(T),bool) :- welltyped(T,nat). welltyped(if(T1,T2,T3),T) :- welltyped(T1,bool), welltyped(T2,T), welltyped(T3,T).

© Ralf Lämmel, 2009-2011 unless noted otherwise 206 Prolog Conditional evaluation for typed NB

main(Input) :- see(Input), read(Term), seen, format('Input term: ~w~n',[Term]), welltyped(Term, Type), format('Type of term: ~w~n',[Type]), manysteps(Term,X), show(X,Y), format('Value of term: ~w~n',[Y]).

© Ralf Lämmel, 2009-2011 unless noted otherwise 207 The Untyped Lambda Calculus

© Ralf Lämmel, 2009-2011 unless noted otherwise 208 Summarizing Summarizing the system

This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU. The grammar and (small-step) operational semantics of lambda-calculus Formalizationlambda-calculus of the lambda calculus Evaluation rules (call-by-name) Syntax Summarizing

Summarizing the system Syntax t ::=x • t ::=x t t ￿ t t￿ t1 → t1￿ t → t￿ λx.t Terms → → t1 t2 t1￿ t2 vt vt￿ 1 2 → 1 2 → The grammar and (small-step) operational semantics of tt (λx.t) v [v/x]t lambda-calculus → v ::=λx.t Values (normal forms) Evaluation rules (call-by-name)v ::=λx.t Syntax is the smallest binary relation on • Evaluation → terms satisfying the rules t ::=x t t ￿ t t￿ 1 → 1 → λx.t 34 / 36 t1 t2 t1￿ t2 vt vt￿ tt → → (λx.t) v [v/x]t → v ::=λx.t © Ralf Lämmel, 2009-2011 unless noted otherwise 209 is the smallest binary relation on → terms satisfying the rules

34 / 36 Prolog Syntax of the untyped lambda calculus

term(var(X)) :- variable(X). term(app(T1,T2)) :- term(T1), term(T2). term(lam(X,T)) :- variable(X), term(T).

value(lam(X,T)) :- variable(X), term(T).

variable(X) :- atom(X). Variables are Prolog atoms.

© Ralf Lämmel, 2009-2011 unless noted otherwise 210 Prolog λ: sample term

app(app(app( % TEST (if-then-else) lam(l,lam(m,lam(n,app(app(var(l),var(m)),var(n))))), % Church Boolean True lam(t,lam(f,var(t)))), We illustrate Church Booleans % Church Numeral 0 and numerals. That is, we use a conditional (TEST) to select lam(s,lam(z,var(z)))), either C0 or C1. % Church Numeral 1 lam(s,lam(z,app(var(s),var(z))))).

© Ralf Lämmel, 2009-2011 unless noted otherwise 211 Prolog Evaluation rules of the untyped lambda calculus

eval(app(T1,T2),app(T3,T2)) :- eval(T1,T3).

eval(app(V,T1),app(V,T2)) :- Substitution (as needed for beta reduction) is the value(V), interesting part--both in the eval(T1,T2). formal setting. and in Prolog.

eval(app(lam(X,T1),V),T2) :- value(V), substitute(V,X,T1,T2).

© Ralf Lämmel, 2009-2011 unless noted otherwise 212 This slide is derived from Jaakko Järvi’s slides for his course ”ProgrammingIntroduction Languages”, CPSC 604 @ TAMU. InductiveSubstitution definition of substitution in λ calculus

[N/x]x = N [N/x]y = y, y any variable different from x

[N/x](M1 M2)=([N/x]M1)([N/x]M2) [N/x](λx.M)=λx.MIntroduction Variable[N/x binding](λy.M)= —λ precisey.([N/x definition]M), y not free in N Alpha renaming can be applied freely, variables drawn from the infinite FV(M) defines the set of free variables in the term M pool of variable names FV(x)=Examples:x { } FV(MN)=FV(M) FV(N) [z/x]x ∪ FV(λx.M)=FV(M) x [z/x](λx.xx) \{ }

© Ralf Lämmel, 2009-2011[z/x unless](λ ynoted.yx otherwise) 213 [Spotz/x]( freeλz. andxz) bound occurrences here:

12 / 36 (λx.y)(λy.y) λx.(λy.xy)y

Combinator —atermwithnofreevariables(alsoclosed term)

9 / 36 Substitution 1/3 Prolog

substitute(N,X,var(X),N).

substitute(_,X,var(Y),var(Y)) The simple :- cases \+ X == Y.

substitute(N,X,app(M1,M2),app(M3,M4)) :- substitute(N,X,M1,M3), substitute(N,X,M2,M4).

substitute(_,X,lam(X,M),lam(X,M)).

© Ralf Lämmel, 2009-2011 unless noted otherwise 214 Substitution 2/3 Prolog

substitute(N,X,lam(Y,M1),lam(Y,M2)) :- \+ X == Y, Push down substitution into the freevars(N,Xs), body of the lambda abstraction if its bound variable Y does not \+ member(Y,Xs), occur freely in the target substitute(N,X,M1,M2). expression N.

© Ralf Lämmel, 2009-2011 unless noted otherwise 215 Substitution 3/3 Prolog

substitute(N,X,lam(Y,M1),lam(Z,M3)) :- \+ X == Y, If Y occurs freely in N, then we need to perform alpha freevars(N,Xs), conversion for Y. Hence, we member(Y,Xs), find a fresh variable and freshvar(Xs,Z), convert the body M1 before we continue with the original substitute(var(Z),Y,M1,M2), substitution. substitute(N,X,M2,M3).

© Ralf Lämmel, 2009-2011 unless noted otherwise 216 Free variables Prolog

freshvar(Xs,X) :- freshvar(Xs,X,0).

freshvar(Xs,N,N) :- We use numbers as generated variables. We find the smallest \+ member(N,Xs). number X that is not in Xs. freshvar(Xs,X,N1) :- member(N1,Xs), N2 is N1 + 1, freshvar(Xs,X,N2).

© Ralf Lämmel, 2009-2011 unless noted otherwise 217 An Applied (Untyped) Lambda Calculus

© Ralf Lämmel, 2009-2011 unless noted otherwise 218 Prolog Syntax of the applied, untyped lambda calculus

:- multifile term/1. We merge the syntax of NB :- ['../untyped/term.pro']. and lambda calculus. In this :- ['../../nb/untyped/term.pro']. manner, we get an applied lambda calculus (with all the applied bits of NB). :- multifile value/1. :- ['../untyped/value.pro']. :- ['../../nb/untyped/value.pro'].

© Ralf Lämmel, 2009-2011 unless noted otherwise 219 Prolog λ: sample term

app(app( evaluates to 4 % Twice lam(f,lam(x,app(var(f),app(var(f),var(x))))), % Increment function lam(x,succ(var(x)))), % 2 succ(succ(zero))).

© Ralf Lämmel, 2009-2011 unless noted otherwise 220 Prolog λ: sample term app(app( evaluates to false % CBV fixed point combinator lam(f,app( lam(x,app(var(f),lam(y,app(app(var(x),var(x)),var(y))))), lam(x,app(var(f),lam(y,app(app(var(x),var(x)),var(y))))))),

% iseven lam(e,lam(x,if( iszero(var(x)), We construct the recursive true, iseven function and apply it to 3. if( iszero(pred(var(x))), false, app(var(e),pred(pred(var(x))))))))),

% Argument to be tested succ(succ(succ(zero)))

).

© Ralf Lämmel, 2009-2011 unless noted otherwise 221 Prolog Evaluation rules the applied, untyped lambda calculus

:- multifile eval/2. Essentially, we merge the evaluation rules for NB and :- multifile substitute/4. the untyped lambda calculus. :- multifile freevars/2. However, we also need to :- ['../untyped/eval.pro']. upgrade substitution to cope :- ['../../nb/untyped/eval.pro']. with NB’s construct. :- ['substitute.pro']. :- ['freevars.pro'].

© Ralf Lämmel, 2009-2011 unless noted otherwise 222 Prolog Substitution for applied part

substitute(_,_,true,true). substitute(_,_,false,false). substitute(_,_,zero,zero). substitute(N,X,succ(T1),succ(T2)) :- substitute(N,X,T1,T2). substitute(N,X,pred(T1),pred(T2)) :- substitute(N,X,T1,T2). substitute(N,X,iszero(T1),iszero(T2)) :- substitute(N,X,T1,T2). substitute(N,X,if(T1a,T2a,T3a),if(T1b,T2b,T3b)) :- substitute(N,X,T1a,T1b), substitute(N,X,T2a,T2b), This is all trivial code. We substitute(N,X,T3a,T3b). simply push substitution into NB’s terms.

© Ralf Lämmel, 2009-2011 unless noted otherwise 223 Prolog Free variables for applied part

freevars(true,[]). freevars(false,[]). freevars(zero,[]). freevars(succ(T),FV) :- freevars(T,FV). This is all trivial code. We freevars(pred(T),FV) :- freevars(T,FV). simply traverse (and freevars(iszero(T),FV) :- freevars(T,FV). union) over NB’s terms. freevars(if(T1,T2,T3),FV) :- freevars(T1,FV1), freevars(T2,FV2), freevars(T3,FV3), union(FV1,FV2,FV12), union(FV12,FV3,FV).

© Ralf Lämmel, 2009-2011 unless noted otherwise 224 An Applied (Typed) Lambda Calculus

© Ralf Lämmel, 2009-2011 unless noted otherwise 225 This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU. Revised syntax

• Lambda abstractions are annotated with types:

λx : T.t

• Grammar of types:

T ::= bool

nat

T→T

© Ralf Lämmel, 2009-2011 unless noted otherwise 226 Prolog Revised syntax

Build on top of untyped applied lambda calculus. :- ['../applied/term.pro']. :- ['../applied/value.pro']. The untyped version is no longer to be used. term(lam(X,A,T)) :- variable(X), type(A), term(T). term(fix(T)) :- term(T).

value(lam(X,A,T)) :- variable(X), type(A), term(T).

type(bool). type(nat). type(fun(A1,A2)) :- type(A1), type(A2).

© Ralf Lämmel, 2009-2011 unless noted otherwise 227 This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU. Typing rulesAdding types to lambda-calculusfor simply-typed Typing rules for simply-typed lambda calculus lambda calculus

x, y, z, f , g range over variables s, t, u range over terms S, T , U range over types

T-Variable T-Abstraction x : T Γ Γ, x : T u : U ∈ ￿ Γ x : T Γ λx : T .u : T U ￿ ￿ → T-Application Γ t : U T Γ u : U ￿ → ￿ Γ tu: T ￿

© Ralf Lämmel, 2009-2011 unless noted otherwise 228

11 / 42 Prolog Typing rules for simply-typed lambda calculus

:- ensure_loaded('../../shared/map.pro').

welltyped(G,var(X),A) :- member((X,A),G).

welltyped(G,app(T1,T2),B) :- welltyped(G,T1,fun(A,B)), welltyped(G,T2,A).

welltyped(G1,lam(X,A,T),fun(A,B)) :- update(G1,X,A,G2), welltyped(G2,T,B).

© Ralf Lämmel, 2009-2011 unless noted otherwise 229 Prolog Lifted typing rules of NB

welltyped(T,A) :- welltyped([],T,A). We had to rewrite the typing rules for NB to incorporate the welltyped(_,true,bool). typing context. welltyped(_,false,bool). welltyped(_,zero,nat). welltyped(G,succ(T),nat) :- welltyped(G,T,nat). welltyped(G,pred(T),nat) :- welltyped(G,T,nat). welltyped(G,iszero(T),bool) :- welltyped(G,T,nat). welltyped(G,if(T1,T2,T3),T) :- welltyped(G,T1,bool), welltyped(G,T2,T), welltyped(G,T3,T).

© Ralf Lämmel, 2009-2011 unless noted otherwise 230 Adding types to lambda-calculus Evaluation rules

Syntax EvaluationSmall-step rules semantics t ::=x v tt t t ￿ t t￿ | | 1 → 1 → v ::=λx :T .t true false t1 t2 t1￿ t2 vt vt￿ | | → → T ::=bool T T (λx :T .t) v [v/x]t | →

￿ Types play no role in the is thesemantics. smallest binary relation t =terms,v =value,T =type → © Ralf Lämmel, 2009-2011on unless terms noted otherwise satisfying231 the rules Note again that evaluation rules do not bother with types! Type checker’s task to reject programs that try to apply rules for meaningless types This corresponds (to some extent) to language implementations

14 / 42 Prolog Update on evaluation rules

Build on top of untyped applied lambda calculus. :- ['../applied/eval.pro'].

“Type erasure” for lambdas eval(lam(X,_,T),lam(X,T)). substitute(N,X,lam(Y,_,M),T) :- substitute(N,X,lam(Y,M),T). freevars(lam(X,_,M),FV) :- freevars(lam(X,M),FV).

© Ralf Lämmel, 2009-2011 unless noted otherwise 232 Aside: general recursion The fix operator

We discussed the fix point operator (Y-combinator, fix), and showed its definition in untyped lambda calculus Just like self-application, fix cannot be typed in simply-typed lambda

This slidecalculus is derivedAside: from general Jaakko Järvi’s recursion slides for his course ”Programming Languages”, CPSC 604 @ TAMU. Simple fix: add fix as a primitive The fix operator The fix construct

fix (λx : T .t) [(fix (λx : T .t))/x] t WeSince discussed fixed point theAside: fixcombinators general point recursion operator are (Y-combinator,→ fix), and showed not typeable in this calculus, we its definition in untyped lambda calculus t t￿ The fix operatorneed fix instead. Typing→ rule Just like self-application, fix cannot befix typedt infix simply-typedt￿ lambda Syntax fix. → calculus Γ t : T T We discussed the fixt point::= ... | operatorfix t (Y-combinator,￿ → fix), and showed Simple fix: add fix as a primitive Γ fix t : T its definition in untyped lambda calculus ￿ Just like self-application, fix cannot be typed in simply-typed lambda fix (λx : TEvaluation.t) [(fix rules(λx : T .t))/x] t calculus → 16 / 50 Simple fix: add fix as a primitivet t￿ → fix t fix t￿ → fix (λx : T .tΓ) t [(: fixT (λTx : T .t))/x] t ￿→ → © Ralf Lämmel, 2009-2011 unless noted otherwise Γ tfix233 tt￿ : T ￿ → fix t fix t￿ → Γ t : T T 16 / 50 ￿ → Γ fix t : T ￿

16 / 50 Prolog The fix construct

Evaluation rules eval(fix(T1),fix(T2)) :- eval(T1,T2). eval(fix(lam(X,T1)),T2) :- substitute(fix(lam(X,T1)),X,T1,T2). substitute(N,X,fix(T1),fix(T2)) :- substitute(N,X,T1,T2). freevars(fix(T),FV) :- freevars(T,FV).

Typing rule

welltyped(G,fix(T),A) :- welltyped(G,T,fun(A,A)).

© Ralf Lämmel, 2009-2011 unless noted otherwise 234 • Summary: Prolog likes Lambdas. ✦ Evaluation rules are easily implemented. ✦ Typing rules, ditto. ✦ Language composition and extension works fine. • Prepping: See the 3 lectures on λ-calculi. • Lab: λ-calculi in Prolog • Outlook: ✦ Another domain for calculi: distribution. ✦ with Haskell.

© Ralf Lämmel, 2009-2011 unless noted otherwise 235