Centro Universitário do Triângulo Cálculo Lambda 1. Introdução A elaboração de modelos de computação (resolução de problemas por uma máquina) baseia-se em trabalhos de dois pesquisadores com enfoques bastante diferentes: Máquinas de Turing (Alan Turing, 1936) Cálculo Lambda (Alonzo Church, 1936) Utilidade do Cálculo Lambda em Programação Funcional: Ponto de partida: Maioria das Linguagens de Programação Funcional são semelhantes e diferem somente em aspectos sintáticos; Uma linguagem funcional de alto nível pode ser compilada em código intermediário com uma sintaxe e semântica extremamente simples. Essa linguagem é expressa em termos de cálculo lambda; O cálculo lambda é suficientemente expressivo para permitir a codificação de uma linguagem funcional de alto nível; Algoritmos para a resolução de problemas computacionais expressos em cálculo lambda podem ser facilmente implementados de diferentes formas. O cálculo lambda serve como uma ponte entre linguagens funcionais de alto nível e suas implementações de baixo nível. Razões para a apresentação do cálculo lambda como uma intermediária: É uma linguagem extremamente simples, consistindo de somente algumas poucas construções sintáticas e de uma semântica simples; Uma implementação do cálculo lambda necessita somente de suportar algumas construções simples. A sua semântica simples nos permite analisar facilmente a correção de sua implementação. É uma linguagem expressiva, a qual é suficientemente poderosa para expressar todos os programas funcionais e, por conseguinte, todas as funções computáveis. A linguagem Lisp foi inspirada pelo cálculo lambda, um formalismo desenvolvido nos anos 30 por Alonzo Church como parte de um sistema para lógicas de ordem superior e teoria das funções [HS86]. O cálculo lambda pode ser considerado como uma linguagem de programação abstrata, onde o conceito de computação, isto é, as maneiras como funções podem ser combinadas para formar outras funções, aparece em toda sua generalidade e de uma forma pura, despida de complicações sintáticas. A principal característica do cálculo lambda é tratar funções como cidadãos de primeira classe, isto é, entidades que podem ser, como um dado qualquer, utilizadas como argumentos e retornadas como valores de outras funções [Sto77]. Esta característica é preservada na linguagem Lisp onde dados e funções têm exatamente o mesmo ``status'' 2. Notação Inicialmente, vamos introduzir a notação utilizada no cálculo lambda. Considere a expressão matemática ; esta expressão pode ser interpretada como: Função de x; Função de y ou; 1
Uma função de ambos (x e y): Para eliminar esta ambigüidade, em geral, são adotadas notações ad hoc como, por exemplo, atribuir um nome arbitrário a cada função. No cálculo lambda, Church propõe uma maneira sistemática para representar uma função de uma ou mais variáveis, dada uma expressão matemática qualquer, sem a necessidade de atribuir um nome a esta função. Isto é feito utilizando o símbolo auxiliar : Exemplo: As equações e são escritas na notação lambda como: Usando o fato de serem permitidas funções cujos valores são outras funções, pode-se simplificar a notação utilizada para as funções e acima, eliminando a necessidade de notações específicas para funções de duas ou mais variáveis: Exemplo: A equação é agora escrita como: Esta nova notação permite que apenas funções de uma variável sejam consideradas, simplificando a apresentação da linguagem. Exemplo: A partir das funções abaixo, converta para a notação Lambda e encontre o resultado. a) f1(x) = x 2 + 2; f1(3) =? b) f2(y) = y 3 + 4; f2(2) =? c) f3(x) = x + x.y f3(4) =? d) f4(y) = x + x.y f4(3) =? e) f5(x,y) = x + x.y f5(4,3) =? f) f6(x,k) = x k f6(5,2) =? g) f7(x,y) = f1(x) + f2(y) f7(3,2) =? h) f8(y,x) = f1(x) + f2(y) f8(3,2) =? 3. Sintaxe Formalmente, a linguagem do cálculo lambda é determinada pela especificação dos seguintes conjuntos: Um conjunto infinito V de símbolos de variável. Um conjunto finito, infinito ou vazio C de símbolos de constante. 2
A sintaxe de uma expressão lambda em notação BNF é dada abaixo: <expr> ::= <constante> <variavel> <expr><expr> λ <variavel>.<exp> <constante> ::= a b c d <variavel> ::= x y w z ou, de forma mais estruturada (G. Revesz): <expr> ::= <constante> <variavel> <aplicação> <abstração> <aplicação> ::= (<expr>) <expr> <abstração> ::= λ <variavel>.<exp> <constante> ::= a b c d e f g 0 1... 9 <variavel> ::= x y w z Exercício: Verificar se a linguagem acima é capaz de gerar os seguintes Lambda-Termos: a) λx.x b) λx. λy.(y) x c) λx.(f)x d) (f)3 e) λf.(f)2 f) (λy.(x)y) λx.(d)x As variáveis e constantes são chamadas átomos. Termos arbitrários são representados por letras maiúsculas (M, N, P, Q, etc.) e quando dois termos e são sintaticamente idênticos, escreve-se. 4. Sintaxe da Linguagem Lambda Duas construções destacam-se na Linguagem Lambda: a) Abstração Lambda: Permite abstrair a definição da função. Por exemplo, a função f(x) = x 3 + 4 é denotada pelo seguinte expressão lambda: λx. x 3 + 4, que pode ser interpretado como: função tal que, para um argumento arbitrário x resulta em x 3 + 4 b) Aplicação Lambda: Determina o valor da função aplicada a um dado parâmetro. Por exemplo, a função f acima aplicada ao parâmetro 2 é denotada pelo seguinte expressão lambda: (λx. x 3 + 4)(2), que pode ser interpretado como: aplicação da função λx. x 3 + 4 ao valor 2 Convenção: M, N, L... denotam termos da Linguagem Lambda; No caso acima, supondo que: M denota: x 3 + 4 N denota: λx. x 3 + 4 P denota 2 3
Então o termo (λx. x 3 + 4)(2) pode ser denotado como segue: (λx.m)(p) (N)(P) OBS: Qual a diferença entre as expressões lambdas abaixo? a) (λk.(λx.x k )(5))(2) b) (λk.(λx.x k ))(5)(2) Solução: a) (λk.(λx.x k )(5))(2) = (λk.5 k )(2) = 5 2 = 25 b) (λk.(λx.x k ))(5)(2) = (λx.x 5 )(2) = 2 5 = 32 5. A Semântica operacional do Cálculo Lambda A semântica de um termo lambda está relacionada com os conceitos de variável livre, ligada (ou atada), substituição de variável livre e regra de redução beta. Variável livre e ligada Considere a expressão: λx (x+y)(4). Para avaliar esta expressão necessitamos: Saber o valor global de y; Não necessitamos saber o valor global de x, pois é o parâmetro formal da função; Assim vemos que: x e y possuem um status bastante diferente; A razão é que x ocorre ligado (atado) pelo λx, é somente um encaixe dentro do qual o argumento 4 é colocado quando a abstração-λ for aplicada ao argumento. Por outro lado, y não é ligado por nenhuum λ e assim ocorre livre na expressão. A ocorrência de uma variável é atada (ligada) se há uma expressão-λ envolvente qua a amarra, senão é livre. No exemplo a seguir (notação pré-fixada), x e y ocorrem atados (ligados), z porém, ocorre livre: λx. + ((λy. + y z) 7 )x Resumindo: Variável Ligada: se está dentro do escopo de uma abstração lambda; Variável Livre: caso contrário Exemplo: a) No termo λx.x k, as variáveis x e k são ditas ligada e livre, respectivamente. b) No termo λx.λk.x k (ou (λx.(λk.x k ))) as variáveis x e k são ditas ligadas. 4
6. Substituição de Variável Livre Sejam x uma variável e M, P termos lambda. A Substituição de uma Variável Livre x por P em M é denotada por: [P/x]M é simplesmente a substituição de todas as ocorrências de x em M pelo termo P. Exemplo: A substituição da variável livre x por 5 em λx.x k é como segue: [5/x] λk.x k = λk.5 k 7. Regra de Redução Beta Sejam x uma variável e M, P termos lambda. A Regra de Redução Beta (Regra de Redução β) de um termo (λx.m)(p) é dada pela substituição de x por P em M, ou seja: [P/x]M Note-se que x é uma variável ligada em λx.m, mas é livre em M, o que garante a coerência da definição acima. 8. Semântica de um termo lambda A Semântica de um Termo Lambda dado por uma função aplicada a um parâmetro é dada pelas aplicações sucessivas possíveis da regra de redução beta. Exemplo: A semântica do termo (λk.(λx.x k )(5))(2) é dada pela sucessiva aplicação da regra de redução beta como segue: (λk.(λx.x k )(5))(2) = aplicação da regra de redução beta em k [2/k](λx. x k )(5) = substituição da variável livre k (λx. x 2 )(5) = aplicação da regra de redução beta em x [5/x]( x 2 ) = substituição da variável livre x 5 2 = 25 Exercício: Converta as expressões abaixo para a linguagem Lambda e resolva-as a partir da Regra de Redução Beta. i) f1(x) = x 2 + 2; f1(3) =? j) f2(y) = y 3 + 4; f2(2) =? k) f3(x) = x + x.y f3(4) =? l) f4(y) = x + x.y f4(3) =? m) f5(x,y) = x + x.y f5(4,3) =? n) f6(x,k) = x k f6(5,2) =? o) f7(x,y) = f1(x) + f2(y) f7(3,2) =? p) f7(y,x) = f1(x) + f2(y) f8(3,2) =? 5