x(1). !x(1) x.set(1) - uni koblenz-landaulaemmel/paradigms1011/resource… · programming paradigms...

45
x = 1 let x = 1 in ... x(1). !x(1) x.set(1) Implementing Lambda Calculi in Prolog Ralf Lämmel Programming Paradigms and Formal Semantics <1h Resources: Some of the slides of this lecture were derived from [Järvi], with permission of the original author, by copy & paste or by selection, annotation, or rewording. [Järvi] is in turn based on [Pierce] as the underlying textbook. [Järvi] Slides by J. Järvi: “Programming Languages ”, CPSC 604 @ TAMU (2009) [Pierce] B.C. Pierce: Types and Programming Languages, MIT Press, 2002

Upload: others

Post on 03-Jun-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

x = 1 let x = 1 in ...

x(1).

!x(1) x.set(1)

Implementing Lambda Calculi in Prolog

Ralf Lämmel

Programming Paradigms and Formal Semantics

<1h

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

[Järvi] Slides by J. Järvi: “Programming Languages”, CPSC 604 @ TAMU (2009)[Pierce] B.C. Pierce: Types and Programming Languages, MIT Press, 2002

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

Table of contents

• Untyped NB

• Typed NB

• Untyped lambda calculus

• Applied, untyped lambda calculus

• Applied, typed lambda calculus

192

Objective: compare grammar- and rule-based formalization

with the corresponding Prolog encodings / implementation.

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

Untyped NB

193

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

Syntax of NB

194

More than one syntactic category

Language NB

t ::= terms:v valueif t1 then t2 else t3 conditionalsucc t successorpred t predecessoriszero t test for zero

v ::= values:true constant truefalse constant falsenv numeric value

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

54 / 58

This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.

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

Syntax of NB

195

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).

value(true).value(false).value(NV) :- nvalue(NV).

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

Prolog

We are faithful to the distinction of the

syntactical categories.

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

NB: sample terms

196

Prolog

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

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

supposed to evaluate to 0

supposed to evaluate to false

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

Evaluation rules of NB(SOS)

197

Types for NB

Reminder NB evaluation rules

E-Iszerot → t �

iszero t → iszero t �

E-IszeroZeroiszero 0→ true

E-IszeroSucciszero (succ nv)→ false

E-Succt → t �

succ t → succ t �

E-Predt → t �

pred t → pred t �

E-PredZeropred 0→ 0

E-PredSuccpred (succ nv)→ nv

E-IfTrueif true then t2 else t3 → t2

E-IfFalseif false then t2 else t3 → t3

E-Ift1 → t �

1

if t1 then t2 else t3 → if t �1 then t2 else t3

14 / 28

This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.

Exercise: what happens to our

type system when we omit

the rule?

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

Evaluation rules of NB(SOS)

198

Prolog

% eval(pred(zero),zero).eval(pred(succ(NV)),NV) :- nvalue(NV).eval(succ(T1),succ(T2)) :- eval(T1,T2).eval(pred(T1),pred(T2)) :- eval(T1,T2).eval(iszero(zero),true).eval(iszero(succ(NV)),false) :- nvalue(NV).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).

Disfavoredsemantics

Note: appearances of metavariables in SOS translate into tests for

values.

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

Reflexive, transitive closure

199

Prolog

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

Composing everything

200

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

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

Prolog

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

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

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

Running the NB interpreter

202

$ 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

Typed NB

203

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

Types in NB

204

This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.Types for NB

NB typing rules

First, we need a few new syntactic formsT ::= types:

Bool the Boolean typeNat the type of numeric values

And typing rules:

T-Truetrue : Bool

T-Falsefalse : Bool

T-Ift1 : Bool t2 : T t3 : Tif t1 then t2 else t3 : T

T-Zero0 : Nat

T-Succt : Nat

succ t : Nat

T-Predt : Nat

pred t : Nat

T-Iszerot : Nat

iszero t : Bool

15 / 28

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

NB typing rules

205

Types for NB

NB typing rules

First, we need a few new syntactic formsT ::= types:

Bool the Boolean typeNat the type of numeric values

And typing rules:

T-Truetrue : Bool

T-Falsefalse : Bool

T-Ift1 : Bool t2 : T t3 : Tif t1 then t2 else t3 : T

T-Zero0 : Nat

T-Succt : Nat

succ t : Nat

T-Predt : Nat

pred t : Nat

T-Iszerot : Nat

iszero t : Bool

15 / 28

This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.

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

NB typing rules

206

Prolog

welltyped(true,bool).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).

1:1 mapping

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

Conditional evaluationfor typed NB

207

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]).

Prolog

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

The Untyped Lambda Calculus

208

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

Formalization of the lambda calculus

• Syntax

• Evaluation

209

Summarizing

Summarizing the system

The grammar and (small-step) operational semantics oflambda-calculus

Syntax

t ::=xλx .tt t

v ::=λx .t

Evaluation rules (call-by-name)

t1 → t1�

t1 t2 → t1� t2

t → t �

v t → v t �

(λx .t) v → [v/x ]t

→ is the smallest binary relation onterms satisfying the rules

34 / 36

Summarizing

Summarizing the system

The grammar and (small-step) operational semantics oflambda-calculus

Syntax

t ::=xλx .tt t

v ::=λx .t

Evaluation rules (call-by-name)

t1 → t1�

t1 t2 → t1� t2

t → t �

v t → v t �

(λx .t) v → [v/x ]t

→ is the smallest binary relation onterms satisfying the rules

34 / 36

Summarizing

Summarizing the system

The grammar and (small-step) operational semantics oflambda-calculus

Syntax

t ::=xλx .tt t

v ::=λx .t

Evaluation rules (call-by-name)

t1 → t1�

t1 t2 → t1� t2

t → t �

v t → v t �

(λx .t) v → [v/x ]t

→ is the smallest binary relation onterms satisfying the rules

34 / 36

Terms

Values (normal forms)

This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.

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

Syntax of the untyped lambda calculus

210

Prolog

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

λ: sample term

211

Prolog

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)))), % Church Numeral 0 lam(s,lam(z,var(z)))), % Church Numeral 1 lam(s,lam(z,app(var(s),var(z))))).

We illustrate Church Booleans and numerals. That is, we use a conditional (TEST) to select

either C0 or C1.

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

Evaluation rules of the untyped lambda calculus

212

Prolog

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

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

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

Substitution (as needed for beta reduction) is the

interesting part--both in the formal setting. and in Prolog.

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

Substitution

213

Introduction

Inductive 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 .M[N/x ](λy .M) = λy .([N/x ]M), y not free in N

Alpha renaming can be applied freely, variables drawn from the infinitepool of variable namesExamples:

[z/x ]x[z/x ](λx .x x)

[z/x ](λy .y x)

[z/x ](λz .x z)

12 / 36

This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.

Introduction

Variable binding — precise definition

FV(M) defines the set of free variables in the term M

FV(x) = {x}FV(MN) = FV(M) ∪ FV(N)

FV(λx .M) = FV(M) \ {x}

Spot free and bound occurrences here:

(λx .y)(λy .y)

λx .(λy .x y)y

Combinator — a term with no free variables (also closed term)9 / 36

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

Substitution 1/3

214

Prolog

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

substitute(_,X,var(Y),var(Y)) :- \+ 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)).

The simple cases

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

Substitution 2/3

215

Prolog

substitute(N,X,lam(Y,M1),lam(Y,M2)) :- \+ X == Y, freevars(N,Xs), \+ member(Y,Xs), substitute(N,X,M1,M2).

Push down substitution into the body of the lambda abstraction if

its bound variable Y does not occur freely in the target

expression N.

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

Substitution 3/3

216

Prolog

substitute(N,X,lam(Y,M1),lam(Z,M3)) :- \+ X == Y, freevars(N,Xs), member(Y,Xs), freshvar(Xs,Z), substitute(var(Z),Y,M1,M2), substitute(N,X,M2,M3).

If Y occurs freely in N, then we need to perform alpha

conversion for Y. Hence, we find a fresh variable and

convert the body M1 before we continue with the original

substitution.

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

Free variables

217

Prolog

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

freshvar(Xs,N,N) :- \+ member(N,Xs).

freshvar(Xs,X,N1) :- member(N1,Xs), N2 is N1 + 1, freshvar(Xs,X,N2).

We use numbers as generated variables. We find the smallest number X that is not in Xs.

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

An Applied (Untyped) Lambda Calculus

218

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

Syntax of the applied, untyped lambda calculus

219

Prolog

:- multifile term/1.:- ['../untyped/term.pro'].:- ['../../nb/untyped/term.pro'].

:- multifile value/1.:- ['../untyped/value.pro'].:- ['../../nb/untyped/value.pro'].

We merge the syntax of NB and lambda calculus. In this manner, we get an applied

lambda calculus (with all the applied bits of NB).

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

λ: sample term

220

Prolog

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

evaluates to 4

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

λ: sample term

221

Prolog

app(app(

% 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)), true, if( iszero(pred(var(x))), false, app(var(e),pred(pred(var(x))))))))),

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

).

We construct the recursive iseven function and apply it to 3.

evaluates to false

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

Evaluation rulesthe applied, untyped lambda calculus

222

Prolog

:- multifile eval/2.:- multifile substitute/4.:- multifile freevars/2.:- ['../untyped/eval.pro'].:- ['../../nb/untyped/eval.pro'].:- ['substitute.pro'].:- ['freevars.pro'].

Essentially, we merge the evaluation rules for NB and the untyped lambda calculus. However, we also need to

upgrade substitution to cope with NB’s construct.

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

Substitution for applied part

223

Prolog

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), substitute(N,X,T3a,T3b).

This is all trivial code. We simply push substitution

into NB’s terms.

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

Free variables for applied part

224

Prolog

freevars(true,[]).freevars(false,[]).freevars(zero,[]).freevars(succ(T),FV) :- freevars(T,FV).freevars(pred(T),FV) :- freevars(T,FV).freevars(iszero(T),FV) :- freevars(T,FV).freevars(if(T1,T2,T3),FV) :- freevars(T1,FV1), freevars(T2,FV2), freevars(T3,FV3), union(FV1,FV2,FV12), union(FV12,FV3,FV).

This is all trivial code. We simply traverse (and

union) over NB’s terms.

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

An Applied (Typed) Lambda Calculus

225

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

Revised syntax

• Lambda abstractions are annotated with types:

λx : T.t

• Grammar of types:

T ::= bool

nat

T→T

226

This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.

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

:- ['../applied/term.pro'].:- ['../applied/value.pro'].

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).

The untyped version is no longer to be used.

Prolog

Build on top of untyped applied lambda calculus.

Revised syntax

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

Typing rules for simply-typed lambda calculus

228

Adding types to lambda-calculus

Typing rules for simply-typed lambda calculus

x , y , z , f , g range over variabless, t, u range over termsS , T , U range over types

T-Variablex : T ∈ Γ

Γ � x : T

T-AbstractionΓ, x : T � u : U

Γ � λx : T .u : T → U

T-ApplicationΓ � t : U → T Γ � u : U

Γ � t u : T

11 / 42

This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.

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

Prolog

:- 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).

Typing rules for simply-typed lambda calculus

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

Lifted typing rules of NB

230

Prolog

welltyped(T,A) :- welltyped([],T,A).

welltyped(_,true,bool).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).

We had to rewrite the typing rules for NB to incorporate the

typing context.

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

Small-step semantics

231

Adding types to lambda-calculus

Evaluation rules

Syntax

t ::=x | v | t tv ::=λx :T .t | true | falseT ::=bool|T �T

t = terms, v = value, T = type

Evaluation rules

t1 → t1�

t1 t2 → t1� t2

t → t �

v t → v t �

(λx :T .t) v → [v/x ]t

→ is the smallest binary relationon terms satisfying the rules

Note again that evaluation rules do not bother with types!Type checker’s task to reject programs that try to apply rules formeaningless typesThis corresponds (to some extent) to language implementations

14 / 42

Types play no role in the semantics.

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

:- ['../applied/eval.pro'].

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).

Update on evaluation rules

232

“Type erasure” for lambdas

Prolog

Build on top of untyped applied lambda calculus.

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

The fix construct

233

Syntax fix.

t ::= ... | fix t

Aside: general recursion

The fix operator

We discussed the fix point operator (Y-combinator, fix), and showedits definition in untyped lambda calculusJust like self-application, fix cannot be typed in simply-typed lambdacalculusSimple fix: add fix as a primitive

fix (λx : T .t)→ [(fix (λx : T .t))/x ] t

t → t �

fix t → fix t �

Γ � t : T → TΓ � fix t : T

16 / 50

Typing rule

Aside: general recursion

The fix operator

We discussed the fix point operator (Y-combinator, fix), and showedits definition in untyped lambda calculusJust like self-application, fix cannot be typed in simply-typed lambdacalculusSimple fix: add fix as a primitive

fix (λx : T .t)→ [(fix (λx : T .t))/x ] t

t → t �

fix t → fix t �

Γ � t : T → TΓ � fix t : T

16 / 50

Aside: general recursion

The fix operator

We discussed the fix point operator (Y-combinator, fix), and showedits definition in untyped lambda calculusJust like self-application, fix cannot be typed in simply-typed lambdacalculusSimple fix: add fix as a primitive

fix (λx : T .t)→ [(fix (λx : T .t))/x ] t

t → t �

fix t → fix t �

Γ � t : T → TΓ � fix t : T

16 / 50

Evaluation rules

This slide is derived from Jaakko Järvi’s slides for his course ”Programming Languages”, CPSC 604 @ TAMU.

Since fixed point combinators are not typeable in this calculus, we

need fix instead.

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

The fix constructProlog

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

Typing rule

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).

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

• 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.✦ Functional programming with Haskell.

235