Cálculo Lambda Sem Tipos Cálculo lambda sem tipos • Peter Landin (60’s) observou que uma linguagem de programação pode ser compreendida formulando-a em um pequeno núcleo capturando suas características essenciais • outras formas, chamadas de formas derivadas, podem ser compreeendidas traduzindo-as para o núcleo • linguagem núcleo usada por Peter Landin foi o cálculo lambda Cálculo Lambda Sem Tipos UFRGS-2007 p.2/33 Cálculo lambda sem tipos • Cálculo λ inventado por Alonzo Church na década de 20 • toda computação pode ser reduzida a operações básicas de definição de função e aplicação de função • computacionalmente completo Cálculo Lambda Sem Tipos UFRGS-2007 p.3/33 Cálculo lambda sem tipos • LISP (John McCarthy, 50’s) foi implementada baseada no cálculo lambda • cálculo λ largamente utilizado na especificação, projeto e implementação de linguagens de programação • pode ser visto como uma linguagem de programação simples • e, ao mesmo tempo, é um objeto matemático sobre o qual podemos fazer afirmações precisas que podem ser provadas Cálculo Lambda Sem Tipos UFRGS-2007 p.4/33 Outros cálculos • CCS (Milner) - concorrência • Cálculo π (Milner, Parrow e Walker) - concorrência e mobilidade • Cálculo de objetos (Abadi e Cardeli) - para orientação a objetos • vários outros cálculos ... • técnicas utilizadas com cálculo λ podem ser utilizadas também com esses outros cálculos Cálculo Lambda Sem Tipos UFRGS-2007 p.5/33 Conceitos básicos Abstração funcional (ou procedural) é freqüente em praticamente todas as linguagens de programação. A seqüência de computação repetitiva abaixo (succ succ 5) + (succ succ 3) − (succ succ 2) pode ser reescrita na forma add2(5) + add2(3) − add2(2) onde add2(x) = succ succ x Cálculo Lambda Sem Tipos UFRGS-2007 p.6/33 Cálculo λ add2 é simplesmente um nome dado para "função que dado argumento x, retorna x mais dois λx. succ succ x". Esta função existe independente do seu nome e pode ser escrita como: λx. succ succ x Cálculo Lambda Sem Tipos UFRGS-2007 p.7/33 Cálculo λ Na sua forma pura, tudo é função • argumentos aceitos por funções são funções • resultado retornado por uma função também é uma função Sintaxe Abstrata do cálculo λ: t ::= termos: x variável λx.t abstração tt Cálculo Lambda Sem Tipos aplicação UFRGS-2007 p.8/33 Sintaxe abstrata e concreta Gramática anterior descreve a sintaxe abstrata, ou seja descreve termos lambda como árvores. Quando representadas linearmente podem surgir ambigüidades. Que termo (que árvore de sintaxe abstrata), por exemplo, corresponde a xyz ? Ambiguidade na representação linear de árvore é resolvida: • usando parênteses, e adotando convenções que permitam reduzir o seu uso, ou • adotando uma representação linear que evite tais ambiguidades (expressões S) Cálculo Lambda Sem Tipos UFRGS-2007 p.9/33 Sintaxe Abstrata Como resolver a ambigüidade que surge na interpretação de xyz ? • há uma convenção pela qual aplicação é associativa a esquerda. • logo o termo acima tem a mesma interpretação de (x y) z • usando notação S ele seria escrito na forma app(app(x , y), z ) por exemplo Cálculo Lambda Sem Tipos UFRGS-2007 p.10/33 Sintaxe Abstrata Como resolver a ambigüidade que surge na interpretação de λx.λy.x y z • convenção diz que abstrações lambda se extendem o mais a direita possível, ou seja, • o termo acima corresponde a λx.(λy.((x y) z)) • que, usando notação S, ficaria, por exemplo, na forma abs(x , abs(y, app(app(x , y), z ))) Cálculo Lambda Sem Tipos UFRGS-2007 p.11/33 Escopo de variáveis Ocorrência de x é dita ligada quando ocorre no corpo de uma abstração λx.t. Uma ocorrência de x é livre se não é ligada. Exemplos: • ocorrências de x nos termos x y e λy.x y são livres • ocorrência de x nos termos λx.x e λx.λy.x (y z) são ligadas • em (λx.x) x a primeira ocorrência de x é ligada e a segunda é livre Termo é fechado se não possui variáveis livres. Também é chamado de combinador Cálculo Lambda Sem Tipos UFRGS-2007 p.12/33 Semântica operacional Computação consiste basicamente em aplicar função a argumento: (λx.t1 ) t2 −→ [x 7→ t2 ] t1 A notação [x 7→ t2 ]t1 representa o termo que resulta da substituição das ocorrências livres de x em t1 pelo termo t2 . Por exemplo: • o termo (λx. x) y é avaliado para y • o termo (λx. x (λx.x)) (u r) é avaliado para (u r) (λx.x) Termo na forma (λx.t1 ) t2 é chamado redex Cálculo Lambda Sem Tipos UFRGS-2007 p.13/33 Semântica Operacional Existem diversas estratégias para avaliar um termo lambda. Cada uma diz a ordem na qual redexes devem ser avaliados. Considere o termo (λx.x) ((λx.x) (λz.(λx.x) z)). Chamando λx.x de id, por clareza, podemos escrevê-lo na forma id (id (λz.id z)) Esse termo tem 3 redexes (aparecem sublinhados abaixo): id (id (λz.id z)) id (id (λz.id z)) id (id (λz.id z)) Cálculo Lambda Sem Tipos UFRGS-2007 p.14/33 Redução β completa Redução β completa: qualquer redex pode ser escolhido. Uma seqüência possível de redução é a seguinte: id (id (λz.id z)) −→ id (id (λz.z)) −→ id (λz.z) −→ λz.z 6−→ Cálculo Lambda Sem Tipos UFRGS-2007 p.15/33 Ordem normal Ordem normal: preferência pelo redex mais externo, mais a esquerda. Única seqüência de redução possível: id (id (λz.id z)) −→ id (λz.id z) −→ λz.id z −→ λz.z 6−→ Cálculo Lambda Sem Tipos UFRGS-2007 p.16/33 Call by name Chamada por nome ou call by name: como ordem normal, mas não avalia o corpo de uma abstração lambda. Única seqüência possível: id (id (λz.id z)) −→ id (λz.id z) −→ λz.id z 6−→ Cálculo Lambda Sem Tipos UFRGS-2007 p.17/33 Call by value Chamada por valor call by value. Só avalia redexes mais externos e redex só é reduzido se seu lado direito já estiver totalmente reduzido. Usado pela maioria das linguagens id (id (λz.id z)) −→ id (λz.id z) −→ λz.id z 6−→ Cálculo Lambda Sem Tipos UFRGS-2007 p.18/33 Estratégias estritas X estratégias não estritas • Estritas: argumentos de funções são sempre avaliados (mesmo que não sejam utilizados). Call by value é estrita • Não estritas, também chamadas de lazy: somente avalia argumentos que são realmente utilizados. Call by name é não estrita Cálculo Lambda Sem Tipos UFRGS-2007 p.19/33 Semântica Operacional - call by value v ::= λx. t (λx.t) v −→ [x 7→ v] t t1 −→ t′1 (β) (A PP 1) t1 t2 −→ t′1 t2 t2 −→ t′2 (A PP 2) v t2 −→ v t′2 Cálculo Lambda Sem Tipos UFRGS-2007 p.20/33 Múltiplos argumentos Até agora todas as funções são de um único argumento. Como representar funções de dois, ou mais argumentos? Usando funções de alta ordem, ou seja funções que podem retornar funções como resultado • no lugar de λ(x, y).t usamos λx.λy.t • se f = λx.λy.t, ao invés de f (a, b) escrevemos (f a) b Transformação de função de vários argumentos em função de alta ordem é chamada de currificação em homenagem a Haskell Curry (contemporâneo de Church) Cálculo Lambda Sem Tipos UFRGS-2007 p.21/33 Booleanos de Church Codificação de booleanos • tru = λt.λf. t • fls = λt.λf. f Definindo condicional na forma: test = λl. λm. λn. (l m) n temos que: • test tru v w retorna v • test fls v w retorna w Cálculo Lambda Sem Tipos UFRGS-2007 p.22/33 Pares Usando booleanos: • pair = λf. λs. λb. b f s • fst = λp.p tru • snd = λp.p fls Reduzir o termo fst (pair v w) Cálculo Lambda Sem Tipos UFRGS-2007 p.23/33 Numerais de Church • c0 = λs.λz. z • c1 = λs.λz. s z • c2 = λs.λz. s s z • c3 = λs.λz. s s z • ... Cálculo Lambda Sem Tipos UFRGS-2007 p.24/33 Operações aritméticas • scc = λn.λs.λz. s (n s z) • plus = λm.λn.λs.λz.m s (n s z) • times = λm.λn.m (plus n) c0 • iszro = λm.λn (λx fls ) tru • ... Cálculo Lambda Sem Tipos UFRGS-2007 p.25/33 Recursão • a prova de que o cálculo lambda é computacionalmente completo consiste em provar que o poder de expressão da linguagem é igual ao de máquinas de Turing (ou ao da linguagem das funções recursivas, ou outro formalismo equivalente) • o que fizemos foi mostrar como programar algumas funções e valores tais como valores verdade, números inteiros, condicionals, sucessor, predecessor, soma, etc • para ser computacionalmente completo deve ser possível programar comportamento repetitivo! • no cálculo lambda puro se obtém repetição com recursão! Cálculo Lambda Sem Tipos UFRGS-2007 p.26/33 Recursão no cálculo lambda puro • alguns termos no cálculo lambda puro não podem ser avaliados para formas normais: omega = (λx. x x) (λx. x x) • reduzindo esse redex obtemos ômega novamente ! • avaliação de omega exibe um comportamento repetitivo • dizemos que termos sem forma normal divergem Cálculo Lambda Sem Tipos UFRGS-2007 p.27/33 Recursão no cálculo lambda puro • o termo abaixo, chamado combinador de ponto fixo (ou combinador Y call-by-value), pode ser usado para definir funções recursivas fix = λf. (λx. f (λy. x x y)) (λx. f (λy. x x y)) • podemos dizer que é uma versão "melhorada” de omega • difícil de entender por si só, o melhor é entender a forma como ele é usado Cálculo Lambda Sem Tipos UFRGS-2007 p.28/33 Recursão no cálculo lambda puro A função fatorial pode ser definida da seguinte forma: g = λfct. λn. if realeq n c0 then c1 else (times n (fct (prd n))) fatorial = fix g fatorial pode ser usado da seguinte forma fatorial c3 Cálculo Lambda Sem Tipos UFRGS-2007 p.29/33 Extendendo o cálculo λ • toda programação pode ser feita a partir do cálculo λ puro • mais conveniente trabalhar com cálculo λ extendido com outros termos Cálculo Lambda Sem Tipos UFRGS-2007 p.30/33 Formalidades D EFINIÇÃO 1 O conjunto de variáveis livres de um termo t, denotado por FV (t), é definido como segue FV (x) = {x} FV (lambdax.t) = FV (t) {x} FV (t1 t2 ) Cálculo Lambda Sem Tipos = FV (t1 ) ∪ FV (t2 ) UFRGS-2007 p.31/33 Formalidades Substituição de variável livre no corpo de função é o mecanismo usado para passagem de argumento. Ela deve ser definida com cuidado, caso contrário ela pode ter como efeito indesejável a mudança do comportamento da função. Temors que diferem somente no nome de variáveis ligadas são equivalentes [x 7→ s]x = s [x 7→ s]x = y y 6= x [x 7→ s](λy.t1 ) = λy. [x 7→ s]t1 x 6= y e y 6∈ FV (s) [x 7→ s](t1 t2 ) = [x 7→ s]t1 [x 7→ s]t2 Cálculo Lambda Sem Tipos UFRGS-2007 p.32/33 Referências O capítulo 5 de TPL - Bejnamim Pierce tem o necessário para a disciplina. Mais sobre cálculo lambda sem tipo em • The Lambda Calculus - Henk Barendregt, 1984. Compêndio sobre cálculo lambda. • A seção 2 de Lambda calculi with types - Henk Barendregt (no capítulo II do Handbook of Logic in Computer Science disponível também no site da disciplina) é sobre cálculo lambda sem tipos Cálculo Lambda Sem Tipos UFRGS-2007 p.33/33