Introdução ao cálculo-λ



Documentos relacionados
O Cálculo λ sem Tipos

Cálculo Lambda Sem Tipos

Pedro Vasconcelos DCC/FCUP. Programação Funcional 3 a Aula Definição de funções

Pedro Vasconcelos DCC/FCUP. Programação Funcional 2 a Aula Tipos e classes

Pedro Vasconcelos DCC/FCUP. Programação Funcional 5 a Aula Definições recursivas

Programação Funcional - Introdução a Cálculo Lambda

Pedro Vasconcelos DCC/FCUP. Programação Funcional 2 a Aula Tipos e classes

Pedro Vasconcelos DCC/FCUP. Programação Funcional 16 a Aula Árvores equilibradas

Cálculo II. Derivadas Parciais

INF Semântica Formal - Prova II /1

Programação Funcional Aulas 5 & 6

Aula Prática 3. Paradigmas da Programação I / Programação Funcional. ESI/MCC 1 o ano (2005/2006)

Aula Prática 2. Paradigmas da Programação I / Programação Funcional

Nelma Moreira. Departamento de Ciência de Computadores da FCUP. Aula 17

(A1) As operações + e são comutativas, ou seja, para todo x e y em A, x + y = y + x e x y = y x

Layout. Módulos. Normalmente, cada módulo está armazenado num ficheiro com o mesmo nome do módulo. Exemplo.hs

SCC122 Estruturas de Dados. Listas Generalizadas e Polinômios

Paradigmas de Programação

A2. Cada operação é distributiva sobre a outra, isto é, para todo x, y e z em A, x (y + z) = (x y) + (x z) e x + (y z) = (x + y) (x + z)

Aula prática 14. Expressão Lambda

Listas em Haskell. Listas. Linguagem Haskell. Maria Adriana Vidigal de Lima. Faculdade de Computação - UFU. Setembro

Axiomas de corpo ordenado

Alguns Problemas e Exames Resolvidos de LEAmb, LEAN, LEMat, LQ, MEBiol, MEQ 1 o Semestre 2008/2009

Programação imperativa

Expressões Lambda. Programação Funcional. Capítulo 7. José Romildo Malaquias Departamento de Computação Universidade Federal de Ouro Preto

Fundamentos de Programação

Pedro Vasconcelos DCC/FCUP. Programação Funcional 13 a Aula Definição de tipos

Centro Universitário do Triângulo

Introdução à Programação Funcional

Programação Funcional

Programação Funcional. Aula 4. Definindo Funções. José Romildo Malaquias. Departamento de Computação Universidade Federal de Ouro Preto 2011.

Programação Funcional

PCS 3115 (PCS2215) Conteúdo

PCS 3115 (PCS2215) Sistemas Digitais I. Módulo 05 Álgebra Booleana. Prof. Dr. Edison Spina. Sobre o material do Prof. Dr. Marcos A. Simplicio Jr.

Total Escolha 5 (cinco) questões. Justifique todas as passagens. Não é permitido o uso de calculadoras. Boa Sorte!

Linguagem Funcional Haskell

Minicurso 1 Uma introdução ao cálculo lambda e a linguagens de programação funcionais

Pedro Vasconcelos DCC/FCUP. Programação Funcional 4 a Aula Listas

POLINÔMIOS SIMÉTRICOS Carlos A. Gomes, UFRN, Natal RN.

Programação Funcional Aulas 9, 10 & 11

Procedimentos e Algorítmos Programas e Linguagens de Programação Tese de Church-Turing Formas de Representação de Linguagens

Cálculo Diferencial e Integral I

2 A Teoria de Conjuntos - Preliminares

3.4 Álgebra booleana, ordens parciais e reticulados

Universidade Federal do Espírito Santo Centro de Ciências Agrárias CCA UFES Departamento de Computação. Sentenças Abertas

Lambda Cálculo e Programação Funcional. Programação Funcional Bacharelado em Sistemas de Informação Maio

Cálculo Diferencial em R n

Linguagens de Programação Funcional

PROGRAMAÇÃO FUNCIONAL NOTAS DE AULAS

Conceitos de Linguagem de Programação - 2

Funções de Ordem Superior

Aula prática 5. Funções Recursivas

Equações Diofantinas II

Prof. Dr. Marcos Castilho. Departamento de Informática/UFPR. 22 de Fevereiro de 2018

Estruturação de Procedimentos

Exercícios e questões de Álgebra Linear

Matemática 2 aula 11 COMENTÁRIOS ATIVIDADES PARA SALA COMENTÁRIOS ATIVIDADES PROPOSTAS POLINÔMIOS I. P(x) = 4x (x 1) + (x 1)

EXERCÍCIOS DE ÁLGEBRA LINEAR E GEOMETRIA ANALÍTICA (sistemas de equações lineares e outros exercícios)

Teoria da Computação Ficha de exercícios

(A1) As operações + e são comutativas, ou seja, para todo x e y em A, x + y = y + x e x y = y x

Linguagens de Programação. Programação Funcional. Carlos Bazilio

Módulo de Equações do Segundo Grau. Equações do Segundo Grau: Resultados Básicos. Nono Ano

Computabilidade e Complexidade (ENG10014)

A DEFINIÇÃO AXIOMÁTICA DO CONJUNTO DOS NÚMEROS NATURAIS.

LINGUAGENS FORMAIS E AUTÔMATOS

Transcrição:

Introdução ao cálculo-λ Pedro Vasconcelos 13 de Fevereiro de 2014

O que é o cálculo-λ? É um modelo computação universal (i.e., equipotente à máquina de Turing) Ao contrário da MT, o cálculo-λ é também um modelo para linguagens de programação: âmbito de variáveis ordem de computação estruturas de dados recursão... As linguagens funcionais são implementações computacionais do cálculo-λ (Landin, 1964).

Bibliografia 1 Foundations of Functional Programming, notas de um curso de Lawrence C. Paulson, Computer Laboratory, University of Cambrige. 2 Lambda Calculi: a guide for computer scientists, Chris Hankin, Graduate Texts in Computer Science, Oxford University Press.

Plano 1 Sintaxe 2 Reduções e normalização 3 Computação

Plano 1 Sintaxe 2 Reduções e normalização 3 Computação

Termos do cálculo-λ x, y, z,... uma variável é um termo; (λx M) é um termo se x é variável e M é um termo; (M N) é um termo se M e N são termos. exemplos de termos y (λx y) ((λx y) (λx (λx y))) (λy (λx (y (y x)))) não são termos () xλy x(y) (λx (λy y)

Interpretação do cálculo-λ (λx M) é a abstração de x em M. (M N) é a aplicação de M ao argumento N. Exemplos: (λx x) é a função identidade: a x faz corresponder x (λx (λy x)) é a função para cada x dá uma outra função que para cada y dá x Não há distinção entre dados e programas; Não há constantes (e.g. números). Tudo são λ-termos!

Convenções de parêntesis Abreviaturas: λx 1 x 2... x n. M (λx 1 (λx 2... (λx n M)...)) (M 1 M 2... M n ) (... (M 1 M 2 )... M n ) Exemplos: λxy. x (λx (λy x)) λxyz. xz(yz) (λx (λy (λz ((x z) (y z)))))

Ocorrências de variáveis livres e ligadas As ocorrências de x em (λx M) dizem-se ligadas pela abstracção. Uma ocorrência que não é ligada diz-se livre. (λz (λx (y x))) x ligada, y livre Uma variável pode ocorrer livre e ligada no mesmo termo. ((λx x) (λy x)) x ligada, x livre

Ocorrências livres e ligadas de variáveis BV (M) é o conjunto de variáveis com ocorrências ligadas em M (bound variables); FV (M) é o conjunto das variáveis com ocorrências livres em M (free variables). BV (λz (λx (y x))) = {x, z} FV (λz (λx (y x))) = {y} BV ((λx x) (λy x)) = {x, y} FV ((λx x) (λy x)) = {x} Definidas por recursão sobre o termo (ver a bibliografia).

Substituição M[N/x] é o termo resultante da substituição de ocorrências livres de x em M por N. (λx y)[(z z)/y] (λx (z z)) (λx y)[(z z)/x] (λx y) Nota: apenas substitui ocorrências livres de x.

Mudança de variáveis ligadas Os nomes de variáveis ligadas não são relevantes. Exemplo: os dois programas seguintes são equivalentes. int f(int x,int y) { return x+y; } int f(int a,int b) { return a+b; } Esta equivalência é formalizada no cálculo-λ pela conversão-α.

Conversão-α (λx M) α (λy M[y/x]) se y / BV (M) FV (M) Exemplos: λx. xy α λz. xy[z/x] λz. zy λx. xy α λy. xy[y/x] λy. yy porque y FV (xy)

Equivalência-α Consideramos M N se M α N. Exemplo: λx. xy λz. zy Mais geralmente: M N se M M 0 α M 1 α M 2 α α M k N com k 0.

Equivalência-α Consideramos M N se M α N. Exemplo: λx. xy λz. zy Mais geralmente: M N se M M 0 α M 1 α M 2 α α M k N com k 0.

Plano 1 Sintaxe 2 Reduções e normalização 3 Computação

Conversão-β ((λx M) N) β M[N/x] se BV (M) FV (N) = Exemplo: ((λx (x x) ) (y z) ) } {{ } } {{ } β (x x)[(y z)/x] ((y z) (y z)) M N Corresponde à invocação de uma função: x é o parâmetro formal; M é o corpo da função; N é o argumento.

Conversão-β ((λx M) N) β M[N/x] se BV (M) FV (N) = Exemplo: ((λx (x x) ) (y z) ) } {{ } } {{ } β (x x)[(y z)/x] ((y z) (y z)) M N Corresponde à invocação de uma função: x é o parâmetro formal; M é o corpo da função; N é o argumento.

Captura de variáveis A condição BV (M) FV (N) = é necessária para evitar captura de variáveis: ((λx M N { }} { {}}{ (λy x)) y ) β (λy x)[y/x] (λy y) y BV (M) FV (N) Usamos conversões-α para evitar a captura da variável y: ((λx (λy x)) y) α ((λx β (λz x)[x/y] (λz y) M N { }} { {}}{ (λz x)) y ) BV (M) FV (N) =

Captura de variáveis A condição BV (M) FV (N) = é necessária para evitar captura de variáveis: ((λx M N { }} { {}}{ (λy x)) y ) β (λy x)[y/x] (λy y) y BV (M) FV (N) Usamos conversões-α para evitar a captura da variável y: ((λx (λy x)) y) α ((λx β (λz x)[x/y] (λz y) M N { }} { {}}{ (λz x)) y ) BV (M) FV (N) =

Conversão-η (λx (M x)) η M Simplifica uma abstracção redudante: ((λx (M x)) N) β (M N) logo (λx (M x)) M Apenas necessária para garantir a unicidade da forma normal (mais à frente) Não é necessária para a implementação de linguagens funcionais

Currying Não necessitamos de abstrações de duas ou mais variáveis: λxy. M (λx (λy M)) Substituimos os argumentos um de cada vez: ((λxy. M) P Q) (((λx (λy M)) P) Q) β ((λy M)[P/x] Q) β M[P/x][Q/y] Esta codificação chama-se currying em homenagem a Haskell Curry. 1 1 Embora tenha sido Schönfinkel a inventá-la!

Reduções Escrevemos M N se M reduz num passo a N usando conversões β ou η. Escrevemos M N para a redução em múltiplos passos ( ).

Igualdade Escremos M = N se M se pode converter em N por zero ou mais reduções ou expansões; ou seja, a relação ( 1 ). Exemplo: porque a((λy. by)c) = (λx. ax)(bc) a((λy. by)c) a(bc) (λx. ax)(bc) Intuição: se M = N então M e N são termos com o mesmo resultado.

Forma normal Se não existir N tal que M N, então M está em formal normal. M admite forma normal N se M N e N está em forma normal. Exemplo: (λx. a x) ((λy. by) c) a((λy. by) c) a(bc) Logo: (λx. a x) ((λy. by) c) admite forma normal a(bc). Analogia: resultado de uma computação.

Termos sem forma normal Nem todos os termos admitem forma normal: Ω ((λx. x x) (λx. x x)) β (x x)[(λx. x x)/x] ((λx. x x) (λx. x x)) Ω Logo: Ω Ω Ω Analogia: uma computação que não termina.

Confluência Podemos efectuar reduções por ordens diferentes. Exemplo: (λx. a x) ((λy. by) c) a((λy. by) c) a(bc) (λx. a x) ((λy. by) c) (λx. a x) (bc) a(bc) P: Será que chegamos sempre à mesma forma normal? R: Sim (Teorema de Church-Rosser)

Confluência Podemos efectuar reduções por ordens diferentes. Exemplo: (λx. a x) ((λy. by) c) a((λy. by) c) a(bc) (λx. a x) ((λy. by) c) (λx. a x) (bc) a(bc) P: Será que chegamos sempre à mesma forma normal? R: Sim (Teorema de Church-Rosser)

Confluência Teorema (Church-Rosser) Se M = N então existe L tal que M L e N L. A demonstração baseia-se na seguinte propriedade: Diamond property Se M então existe L tal que M 1 M 2 M 1 M 2 L. Mais informação: ver a bibliografia.

Confluência Teorema (Church-Rosser) Se M = N então existe L tal que M L e N L. A demonstração baseia-se na seguinte propriedade: Diamond property Se M então existe L tal que M 1 M 2 M 1 M 2 L. Mais informação: ver a bibliografia.

Estratégias de redução Como reduzir (M N) P? ordem normal: reduzir M e substituir N sem reduzir. 1 M (λx M ) 2 M [N/x] P ordem aplicativa: reduzir M e N antes de fazer a substituição da variável. 1 M (λx M ) 2 N N 3 M [N /x] P

Alguns factos sobre reduções 1 Se a redução por ambas as estratégias termina, então chegam à mesma forma normal 2 Se um termo admite forma normal, esta pode sempre obtida pela redução em ordem normal 3 A redução em ordem aplicativa pode não terminar mesmo quando existe forma normal 4 A redução em ordem normal pode reduzir o mesmo termo várias vezes

Ordem aplicativa: não terminação Seja Ω ((λx. x x) (λx. x x)); vamos reduzir (λx. y) Ω Redução em ordem normal ((λx. y) Ω) β y forma normal Redução em ordem aplicativa ((λx. y) Ω) β ((λx. y) Ω) β não termina

Ordem normal: computação redudante Supondo mult um termo tal que mult N M N M para codificações N, M de números naturais (veremos como mais à frente). Definindo vamos reduzir sqr λx. mult x x sqr (sqr N)

Ordem normal: computação redudante Redução em ordem aplicativa: sqr (sqr N) sqr (mult N N) sqr N 2 mul N 2 N 2 Redução em ordem normal: sqr (sqr N) mult (sqr N) (sqr N) mult (mult N N) (mult N N) } {{ } duplicação

Plano 1 Sintaxe 2 Reduções e normalização 3 Computação

Computação usando cálculo-λ O cálculo-λ é um modelo de computação universal: qualquer função recursiva (computável por uma máquina de Turing) pode ser codificada no cálculo-λ.

Computação usando cálculo-λ Estruturas de dados como boleanos, inteiros, listas, etc. não são primitivas do cálculo-λ. Esta omissão não é fundamental: estas estruturas podem ser definidas usando apenas o cálculo puro. Contudo: implementações de linguagens funcionais usam representações optimizadas por razões de eficiência.

Valores boleanos Definimos: true λxy. x false λxy. y if λpxy. pxy Então: if true M N M if false M N N Exercício: verificar as reduções acima.

Pares ordenados Um constructor e dois selectores: pair λxyf. fxy fst λp. p true snd λp. p false Temos então: fst (pair M N) fst (λf. f M N) (λf. f M N) true true M N M Analogamente: snd (pair M N) N.

Codificar números naturais Usando numerais de Church: 0 λfx. x 1 λfx. f x 2 λfx. f (f x). n λfx. f (... (f x)...) } {{ } n vezes Intuição: n itera uma função n vezes.

Operações aritméticas succ λnfx. f (n f x) iszero λn. n (λx. false) true add λmnfx. m f (n f x) Verificar: succ n n + 1 iszero 0 true iszero (n + 1) false add n m n + m Analogamente: subtracção, multiplicação, exponenciação, etc.

Listas [x 1, x 2,..., x n ] cons x 1 (cons x 2 (... (cons x n nil)...)) Dois constructores, teste da lista vazia e dois selectores: nil λz. z cons λxy. pair false (pair x y) null fst hd λz. fst (snd z) tl λz. snd (snd z)

Listas Verificar: null nil true (1) null (cons M N) false (2) hd (cons M N) M (3) tl (cons M N) N (4) NB: (2), (3), (4) resultam das propriedades de pares, mas (1) não.

Declarações let x = M in N Exemplo: let f = λx. add x x in λx. f (f x)

Tradução para o cálculo-λ Definimos: let x = M in N (λx. N) M Então: let x = M in N N[M/x]

Declarações embricadas Não necessitamos de sintaxe extra: let {x = M; y = N} in P let x = M in (let y = N in P)

Declarações recursivas Tentativa: let f = λx. if (iszero x) 1 (mult x (f (sub x 1))) in f 5 Tradução: (λf. f 5) (λx. if (iszero x) 1 (mult x (f (sub x 1)))) Não define uma função recursiva porque f ocorre livre no corpo da definição.

Declarações recursivas Tentativa: let f = λx. if (iszero x) 1 (mult x (f (sub x 1))) in f 5 Tradução: (λf. f 5) (λx. if (iszero x) 1 (mult x (f (sub x 1)))) Não define uma função recursiva porque f ocorre livre no corpo da definição.

Declarações recursivas: combinadores ponto-fixo Solução: usar um combinador ponto-fixo i.e. um termo Y tal que Y F = F (Y F) para qualquer termo F Definimos o factorial recursivo como: let f = Y (λg x. if (iszero x) 1 (mult x (g (sub x 1)))) in f 5 Note que g ocorre ligada no corpo da função.

Definições recursivas: combinador ponto-fixo Seja: Y F = F (Y F) para qualquer M fact Y (λg x. if (iszero x) 1 (mult x (g (sub x 1)))) Calculemos: fact 5 Y (λg x....) 5 = (λg x....) (Y (λg x....)) 5 } {{ } fact if (iszero 5) 1 (mult 5 (fact (sub 5 1))) if false 1 (mult 5 (fact 4)) mult 5 (fact 4) mult 5 (mult 4 (... (mult 1 1)...)) 120

Combinadores ponto-fixo Y pode ser definido no cálculo-λ puro (Haskell B. Curry): Y λf. (λx. f (x x)) (λx. f (x x)) Verificação: Y F (λx. F(xx)) (λx. F(xx)) F((λx. F(xx)) (λx. F(xx))) F(Y F) Logo Y F = F(Y F) Há uma infinidade de outros combinadores ponto-fixo (ver a bibliografia).