Minicurso 1
Uma introdução ao cálculo lambda e a
linguagens de programação funcionais
Rodrigo Machado
Conteúdo
Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução betaPropriedades da redução beta
Programação em cálculo lambda
Booleanos Números naturais Pares ordenados Listas Definições locais Funções recursivas Funcões de alta ordem
Revisão Referências
Conteúdo
Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução betaPropriedades da redução beta Programação em cálculo lambda
Booleanos Números naturais Pares ordenados Listas Definições locais Funções recursivas Funcões de alta ordem Revisão
Antes de iniciarmos …
Considere os seguintes grupos de linguagens de programação: Grupo 1 : OCAML, F#, LISP, Scheme/Racket, Haskell
Grupo 2 : Javascript, Python, Ruby, C#
Grupo 3 : C, C++, Java, Pascal/Delphi
Quais grupos contém linguagens de programação nas quais vocês já programaram?
Você já ouviu falar antes de Máquinas de Turing, Funções Recursivas Parciais ou Cálculo Lambda?
Antes de iniciarmos (2) …
Suponha uma linguagem de programação com números e valores booleanos. Considere as seguintes construções:
1. execução condicional (if-then e if-then-else)
2. laços de repetição (while e for)
3. definição de variáveis e operador de atribuição
4. definição e aplicação de funções
Se fosse lhe pedido para você escolher três itens acima e jogar fora o item restante, quais itens seriam escolhidos?
Seria possível escrever todos os programas desejados somente com os itens escolhidos?
Origem: notação lambda
Considere a seguinte definição matemática:
f(x) =x2+ 7
A igualdade acima está definindo uma função f, que consome um número e devolve um número.
f(3) = 32+ 7 = 16
A igualdade acima está aplicando a definição def a um valor específico. O propósito original da notação lambda foi resolver a seguinte
ambiguidade:
f(e) =e2+ 7
Afinal, se trata da aplicação def sobre a constantee= 2.716 . . . ou da
Origem: notação lambda (2)
A notação lambda (Church, 1932) permite diferenciar claramente a
definição de uma função de sua respectiva aplicação. f=λx.x2+ 7
Acima temos a definição da função. O λxindica quexdeve ser interpretado como um parâmetro formal, isto é, um nome temporário para o valor a ser recebido pela função.
f(3) = (λx.x2+ 7)(3) = 32+ 7
Acima temos a aplicação da funçãof, definida anteriormente, ao valor 3. Note que o significado da aplicação é a substituição do parâmetro
Origem: cálculo lambda
Ao formalizar as ideias fundamentais de definição e aplicação de funções, se chegou ao cálculo lambda. A versão pura do cálculo não continha nada além de funções (sem números, sem operações).
Ainda na década de 1930, Church e seus alunos (Kleene, Rosser) mostraram que a versão pura do cálculo era tão expressiva quanto outros modelos de computação propostos (em particular, Máquinas de Turing e Funções Recursivas Parciais).
Atualmente, Cálculo Lambda diz respeito a uma grande família de formalismos construídos sobre os mesmos conceitos fundamentais.
Motivação: por que cálculo lambda?
O cálculo lambda original tem aproximadamente 80 anos! Não existiam nem
computadores naquela época! Por que estudar algo tão antigo em 2013?
Algumas razões:
● cálculo lambda foi e continua sendo influente: ele serviu de inspiração para
linguagens de programação como (Lisp e Haskell) e para o estilo de programação funcional nas demais linguagens.
● cálculo lambda (com tipos) é a base para o estudo formal de linguagens de
programação e sistemas de tipos (mesmo as orientadas a objetos e imperativas).
● cálculo lambda (com tipos) possui uma conexão importante com Lógica
Matemática, sendo a base de assistentes de prova como Coq e Agda.
● cálculo lambda é um cálculo minimalista e elegante.
Motivação: funções anônimas hoje em dia
Linguagens de programação e suporte a funções anônimas:
C : não
Pascal : não
C++ : sim (a partir da versão C++11) Javascript : sim
Python : sim Ruby : sim
C# : sim (a partir de versão 3.0) Java : sim (a partir de versão 8)
E é claro, todas as linguagens de programação funcionais/mistas: LISP, Scheme, Clojure, Scala, Ocaml, F#, Haskell, ...
Este minicurso
Objetivos
1. Apresentar as ideias fundamentais de cálculo lambda: termos-lambda, substituição, alfa-equivalência, redução beta
2. Argumentar sobre propriedades do cálculo: confluência de redução beta, universalidade
3. Mostrar como codificar diversos tipos de dados e estruturas de controle como termos-lambda
Abordagem
● conceitual (alguns detalhes formais serão omitidos)
● foco em programação: vamos definir a função fatorial em cálculo lambda puro.
Conteúdo
Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução betaPropriedades da redução beta
Programação em cálculo lambda Booleanos Números naturais Pares ordenados Listas Definições locais Funções recursivas Funcões de alta ordem Revisão
Sintaxe: pré-termos
Começaremos definindo um conjuntoΛ− de pré-termos. Considere um conjunto infinito (mas contável) de nomes (a.k.a parâmetros, identificadores, variáveis) o qual chamaremosVar. Vamos denotar os elementos deVarpor x,y,z, . . .
Definição:o conjuntoΛ− é o menor conjunto tal que:
1. sex∈Varentão x∈Λ− (variáveis)
2. seM∈Λ−e N∈Λ− então@(M,N) ∈Λ− (aplicação)
3. sex∈Vare M∈Λ− entãoλx.M∈Λ− (abstração lambda)
Sintaxe: exemplos
Exemplos de elementos deΛ−: x x y λx.x λx.y (λx.x) y λx.(x y) (λx.x) (λx.x) λx.λy.x λx.λy.y(λx.y) Nota:precisamos de regras claras para evitar ambiguidade na escrita de um pré-termo.Sintaxe: regras de notação
1. O λ engloba tudo à direita (o máximopossível).
λx.x y=λx.(x y)≠ (λx.x)y
2. O operador @ é associativo à esquerda.
x y z= (x y) z≠x (y z)
3. Notação simplificada para λ’s seguidos.
λx y z.M=λx.λy.λz.M x λy.(λx.x y)(z w) ⇕ .... @. .... .. λy... .. @. .... .. @. .... .. w . .. .. z . .. .. λx... .. @. .... .. y . .. .. x . .. .. x
Sintaxe: termos com nomes especiais
Alguns pré-termos são famosos e possuem nomes especiais. Combinadores (lógica combinatorial)
I=λx.x K=λx y.x
S=λx y z.(x z(y z))
Auto-aplicação e ponto fixo
ω=λx.x x Ω=ω ω
Y=λf.(λx.f(x x))(λx.f(x x))
Variáveis livres e ligadas
Definição:dentro do pré-termoλx.M, dizemos queM é o escopo de
λx.
Definição:uma ocorrência dexdentro do escopo deλx é dita ligada. Caso contrário,x ocorre livre.
Exemplo:
a) λx.x y x é ligada, yé livre b) λx.z λz.z x z é livre, ze x são ligadas c) λx.x λx.xy x ex são ligadas,yé livre
Nota:
1. Um mesmo nome por ter ocorrências ligadas e livres no mesmo pré-termo (b).
Variáveis livres e ligadas (2)
Ocorrências livres e ligadas de variáveis têm significados distintos:
● variáveis livresreferem-se a nomes externos (globais).
● variáveis ligadasreferem-se a parâmetros formais (locais). Nomes de variáveis livres são importantes:
expressões distintas⎧⎪⎪⎨⎪⎪ ⎩
sin(π) − 42 +π2
sin(e) − 42 +e2
Nomes de parâmetros formais não são importantes: mesma definição⎧⎪⎪⎨⎪⎪
⎩
λx. sin(x) − 42 +x2 λe. sin(e) − 42 +e2
Variáveis livres e ligadas (3)
Definição:a funçãoFVcomputa as variáveis que ocorrem livres em um pré-termo.
FV(x) = {x}
FV(λx.M) = FV(M) − {x} FV(M N) = FV(M) ∪FV(N)
Definição:um pré-termoM onde FV(M) = {} é fechado, também
Operação de substituição
A operação de substituição
M[x∶=N]
substitui todas as ocorrências livres dexem M porN.
Exemplo: 1) (λx.xy)[x∶=w] = λx.xy 2) (λx.xy)[y∶=w] = λx.xw 3) (λx.xy)[z∶=w] = λx.xy 4) (zλz.z)[z∶=w] = wλz.z 5) (zz)[z∶=λz.zz] = (λz.zz)(λz.zz) 6) (λx.xy)[y∶=x] = (λx.xx)?
Captura de variáveis livres
Problema do Ex. 6: captura de variáveis livres
M ³¹¹¹¹¹¹¹¹¹·¹¹¹¹¹¹¹¹¹¹µ (λx.xy) [y∶= N © x]
● ConsidereM: na posição onde está y, o nomex é ligado
● ConsidereN: o nome xocorre livre
● Ao substituiry porN, podemos colocar um x livre em uma posição onde o mesmo nome xestá ligado.
● Mas nomes livres e ligados possuem interpretações distintas, e isso
altera o significado do termo.
Operação de substituição: definição formal
Definição:operação de substituiçãoevitando captura de variáveis livres x[y∶=P] = { P sex=y x caso contrário (λx.M)[y∶=P] = { λx.M sex=y λx.(M[y∶=P]) se x≠ye x∉FV(P) (M N)[y∶=P] = M[y∶=P] N[y∶=P]
Pergunta:segundo esta definição, qual o resultado de(λx.xy)[y∶=x] ? Resposta:indefinido!
Equivalência alfa
Definição:dois pré-termosM eNsão α-equivalentes (M=αN) sss eles
diferem somente na escolha dos nomes de variáveis ligadas.
Exemplo:
λx.xy=αλz.zy λx.xy≠αλy.yy λx.xx=αλz.zz λy.zy≠αλy.xy
O conceito deα-equivalência captura a intuição que a escolha dos nomes dos parâmetros formais realmente não é importante.
Equivalência alfa: definição formal
Definição:=α é a menor relação de equivalência sobre Λ− tal que
y∉FV(M) λx.M=αλy.(M[x∶=y]) (α) M=αM′ M N=αM′ N M=αM′ N M=αN M′ M=αM′ λx.M=αλx.M′
Termos lambda
Definição:um termo lambda é uma classe de equivalência de pré-termosα-equivalentes.
Notação:vamos denotar por {M}α o termo lambda contendo o
pré-termoM.
Exemplo:
{λx.x}α= {λx.x, λy.y, λz.z, . . .}
{λx.x y}α= {λa.a y, λb.b y, . . . } Definição:Λé conjunto de todos os termos lambda:
Λ= Λ−
Termos lamba: operação de substituição
Operações definidas emΛ− podem ser estendidas para Λ. Lembre: (λx.xy)[y∶=x] ⇒ indefinido Porém, como λx.xy=αλa.ay e (λa.ay)[y∶=x] =λa.ax
podemos estenderM[x∶=N] para termos, obtendo
{λx.xy}α[y∶= {x}α] = {λa.ax}α
Efeito: temos emΛuma operação de substituição que é total e
Termos vs pré-termos
No que segue, vamos falar de termos e não mais de pré-termos.
Contudo, vamos escrever termos usandoMao invés de{M}α, e assumir
que a operação de substituição é total e evita a captura de variáveis livres.
Essa convenção é também chamada convenção de Barendregt, devido à sua utilização no livro deste autor.
Redexes e formas normais
Definição:um redex (reducible expression) é um subtermo de Mcom o formato
(λx.P)Q
e o seu respectivo contractum é
P[x∶=Q]
Definição:um termo que não contenha nenhum redex é chamado
forma normal (ou termo irredutível). Exemplo:
a) λy.(λx.y x)((λy.x) y) contém dois redexes b) λx.λy.x x é uma forma normal
Redução beta
Redução beta descreve a avaliação de termos lambda através de
substituição.
Temos M→βNse obtivermos Natravés da contração de um redex de
M.
Exemplo:
(λz.λx.x z)y →β λx.x y
λy.(λx.y x) ((λy.x) y) →β λy.(λx.y x) x λy.(λx.y x) x →β λy.y x
Redução beta: definição formal
Definição:→β é a menor relação em Λtal que(λx.P) Q→βP[x∶=Q] (β) M→βM′ λx.M→β λx.M′ M→βM′ N M→βN M′ M→βM′ M N→βM′ N Definição:↠β é o fecho transitivo e reflexivo de→β.
Intuitivamente,M↠NquandoM reduz paraNem 0 ou mais passos de redução beta.
Equivalência beta
β-equivalência identifica termos que possuem reescritas confluentes. Definição:=β é a menor relação emΛ tal que
M↠βP N↠βP M=β N
Exemplo:os seguintes termos são β-equivalentes:
M= (λz.λx.x z)y N= (λu.λx.x y) (t t)
P=λx.x y
Equivalência beta: possuir forma normal
Definição:dizemos que um termoM possui forma normal sss M=β N
eNé uma forma normal.
Exemplo:
(λx.x x) possui forma normal (ele é f.n.)
(λx.x x) apossui forma normal (eleβ-reduz para (a a), que é f.n.) (λx.x x) (λx.x x)não possui forma normal (ele β-reduz para si mesmo)
Estratégias de avaliação
Um termoPpode ter diversos redexes e, portanto, avaliar para distintos termos. Exemplo:(considere ω=λx.x x e I=λx.x) .. .... @. .... .. @. .... ..I . .. .. ω . .. .. ω .... .... @. .... .. @. .... ..I . .. ..I . .. .. ω . β . .... @. .... .. @. .... ..I . .. .. ω . .. .. @. .... ..I . .. .. ω . β
Estratégias de avaliação (2)
Definição:Uma estratégia de avaliação é uma escolha fixa para todos os termos de qual redex tem prioridade na redução.
Avaliação preguiçosa (lazy): ● redex mais externo, mais à
esquerda
● realiza a aplicação sem normalizar os argumentos
Avaliação estrita (strict): ● redex mais interno, mais à
esquerda
● normaliza todos os argumentos antes de aplicar a função
Exemplo:
● lazy: (true I Ω) →β (λy.I) Ω →β I
Propriedades de redução beta: confluência
Confluência: (Church-Rosser)
seN←βM→βN′ então existe Ptal que N↠βP↞β N′
Corolário: formas normais são únicas. Exemplo: ω(II) // ω(I) (II)(II) //I(II) //II
Propriedades de redução beta: normalização
Normalização:se o termoM possui forma normalN, então avaliarM usando a estratégia preguiçosa certamente alcança N.
● observe que nem todo termo possui forma normal.
● avaliação estrita pode não alcançar forma normal.
● determinar equivalência beta de termos é um problema indecidível.
Nota:não vamos apresentar neste minicurso as provas de confluência e normalização da redução beta. Contudo, elas são essenciais para a utilização do cálculo como linguagem de programação.
Cálculo lambda: revisão da teoria
Os seguintes conceitos e definições foram apresentados:
● pré-termos(Λ−), variáveis livres e ligadas, operação de substituição,
captura de variáveis livres.
● α-equivalência, termos (Λ), extensão de operações de pré-termos para
termos.
● redexes, formas normais,β-redução,β-equivalência, possuir forma normal, estratégia de avaliação.
● propriedades deβ-redução: confluência, normalização.
Alguns aspectos importantes não foram mencionados (por brevidade):
● provas formais das propriedades de confluência e normalização (β-redução)
● reduçãoη(extensionalidade)
Conteúdo
Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução betaPropriedades da redução beta Programação em cálculo lambda
Booleanos Números naturais Pares ordenados Listas Definições locais Funções recursivas Funcões de alta ordem
Revisão Referências
Cálculo lambda como linguagem de programação
A linguagem de termos lambda juntamente com a redução beta (e uma estratégia de avaliação fixa) compõe uma linguagem de programação
idealizada.
Podemos enxergar a seguinte associação:
● termo lambda = estado da máquina
● redução beta = passo de execução da máquina
● formas normais = valores finais (parada da máquina)
Ainda em 1936, Church mostrou que todas as funções computáveis podem ser descritas em cálculo lambda. Isso significa que esse modelo de computação é universal.
Codificações
Como a linguagem lambda pura provê somente variáveis, abstração lambda e aplicação de termos a termos, é necessário codificar em termos lambda
Dados:
● valores booleanos e operações lógicas
● números, operações aritméticas e operações relacionais
● coleções: pares e listas
Estruturas de controle: ● execução condicional
● definições locais
● recursão
Booleanos
Definição:booleanos de Church:
true=λx y.x false=λx y.y
Intuição
● true consome dois termos, e retorna o primeiro ● false consome dois termos, e retorna o segundo
Construção condicional
Definição:construção if-then-else :
ifathen belsec=λa b c .a b c
Ideia: aplicar o booleano resultante do teste sobre os valores a serem
retornados.
Justifica a definição de valores-verdade como seletores.
Números naturais
Definição:numerais de Church:
0=λf x.x 1=λf x.f x 2=λf x.f (f x) 3=λf x.f (f (f x)) ⋮ n=λf x. n ³¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹·¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹µ f (f (f . . .(f x) . . .))
Operações aritméticas: sucessor
Função sucessor:
succ=λn p q.p (n p q) Ideia da construção:
1. receber um numeral de Church ncom estrutura
n=λf x .f(f. . .(f x) . . .) 2. o resultado deve terpe qligados por lambdas:
λp q. . . .
3. o termo(n p q) muda os f’s emp’s, e ox emq.
Operações aritméticas e relacionais
Definição:operações aritméticas básicas:
add=λ m n p q.m p(n p q) mult=λ m n p q.m (n p) q
exp=λ m n .n m Definição:teste de zero:
isZero=λn.n (λx.false) true
Pares ordenados
Definição:um par(M,N) pode ser representado por pairM Nonde
pair=λ m n b .b m n Exemplo:
pair 0 true=λb.b0 true Definição:funções de acesso ao conteúdo de um par
fst=λp.p true snd=λp.p false
Pares ordenados: predecessor
Usando pares podemos definirpred∶ N → N onde pred(n) =⎧⎪⎪⎨⎪⎪
⎩
0 se n≤ 1 n− 1 caso contrário
Função auxiliar: shiftInc(a,b) = (b,b+ 1)
shiftInc=λp.⟨sndp, succ(sndp)⟩ Definição:o termo pred abaixo implementa a funçãopred
Listas
Listas podem ser consideradas as estruturas de dados fundamentais em linguagens de programação funcionais.
A definição algébrica de uma lista oferece dois construtores:
● empty(lista vazia)
● cons, que recebe um valor e uma lista, e retorna a lista prefixada pelo valor.
Exemplo:
empty
(cons 2 empty)
Listas (2)
Três funções são definidas para acessar o conteúdo da lista:
● isEmptytesta se a lista é vazia
● head retorna o primeiro elemento da lista
● tail retorna a lista resultante da remoção do primeiro elemento. Aplicar head ou tail sobre empty é um erro.
Exemplo:
isEmpty empty => true isEmpty (cons 2 empty) => false head (cons 2 empty) => 2
tail (cons 3 (cons 2 empty)) => (cons 2 empty) head (tail (cons 3 (cons 2 empty))) => 2
Listas (3)
A seguinte codificação implementa as operações de listas sobre cálculo lambda.
Definição:construtores de listas:
empty=λx. true cons=λh t. pair h t
Definição:operações de lista:
isEmpty=λl.l (λx λy.false) head= fst
Definições locais
Programas habitualmente tem o formato
definição 1 definição 2 ...
definição n
programa principal
Em cálculo lambda podemos representar definições locais (não-recursivas) através do seguinte esquema:
Funções recursivas
Considere o problema de definir um termo para executar iteração (laço for) ou definições recursivas em cálculo lambda (função fatorial, por exemplo).
Assuma que temos na linguagem termos primitivos: booleanos, naturais,
succ, pred, isZero, e if-then-else (sem ser via codificação de Church).
Queremos definir uma funçãoI que recebe
● um númeron ● uma funçãof ● um valor inicialx
para o qual(I n f x) resulta em
n
³¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹·¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹µ
Funções recursivas (2)
Tentativa inicial: I=λ n f x.if(isZeron) thenx else(I (predn) f (f x)) Ideia da construção: ● sen= 0 : retorna x● sen> 0 : itera (n− 1) vezes a funçãofno argumento(f x)
Problemas:
● não há memória para armazenar a definição deI
● definição circular
Funções recursivas (3)
Imagine o lado direito da equação como a aplicação de um combinador
Ssobre I.
Nesse caso a equação
I=λ n f x.if (isZeron) then x else(I(predn)f (f x))
se torna
I=S I
onde
S=λ X.λ n f x.if (isZeron) thenx else(X (predn) f (f x)) Nota:veja que a definição deS não é circular!
Pontos fixos
Definição:o ponto fixo (fixed-point, FP) de uma funçãof∶X→X é um elementox∈X tal que f(x) =x
Exemplo:
1) x↦x2 ∶ N → N FP ={0, 1}
2) x↦ ∣x∣ ∶ Z → Z FP ={0, 1, 2, . . .} 3) x↦ −x ∶ Z → Z FP ={0}
4) x↦x− 1 ∶ Z → Z FP ={}
Estamos interessados em encontrar um ponto fixo paraS∶Λ→Λ.
Pontos fixos: combinador Y
Chamamos o termo abaixo de combinador Y (ou combinador de ponto fixo)
Y=λf.(λx.f(x x))(λx.f(x x))
Teorema:o combinador Y produz um ponto fixo para seu argumento
Demonstração:
YS →β
(λx.S(x x)) (λx.S(x x)) →β
S(λx.S(x x)) (λx.S(x x)) =β S(YS)
YS=βS(YS) e, portanto, YSé um ponto fixo deS
Pontos fixos: combinador Y em ação
.... @. .... .. ∎ . .. .. Y → β .... @. .... .. λx... .. @. .... .. @. .... .. x . .. .. x . .. .. ∎ . .. .. λx... .. @. .... .. @. .... .. x . .. .. x . .. .. ∎ →β .... @. .... .. @. .... .. λx... .. @. .... .. @. .... .. x . .. .. x . .. .. ∎ . .. .. λx... .. @. .... .. @. .... .. x . .. .. x . .. .. ∎ . .. .. ∎ →β .... @. .... .. @. .... .. @. .... .. λx... .. @. .... .. @. .... .. x . .. .. x . .. .. ∎ . .. .. λx... .. @. .... .. @. .... .. x . .. .. x . .. .. ∎ . .. .. ∎ . .. .. ∎ ↠β .... @. .... .. @. .... .. @. .... .. @. .... .. @. .... .. @. .... .. . . . . .. .. ∎ . .. .. ∎ . .. .. ∎ . .. .. ∎ . .. .. ∎ . .. .. ∎Pontos fixos: combinador Y em ação (2)
seS =β .... λ...X .. λ n f x... .. if. .... .. X. .... .. (f x) . .... ..f . .. .. (pred n) . .... .. x . .. .. (isZero n)Pontos fixos: combinador Y em ação (3)
então(YS) =β .... λ n f x... .. if. .... .. if. .... .. if. .... .. . . . . .... .. (f (f x)) . .. ..(isZero (pred (pred n))) . .... .. (f x) . .. .. (isZero (pred n)) . .... .. x . .. .. (isZero n)
Funções recursivas e operador Y
Usando Y podemos codificar funções como termos nos baseando em suas
definições recursivas.
Definição recursiva:
fact(n) =⎧⎪⎪⎨⎪⎪ ⎩
1 se n≤ 1
n∗fact(n− 1) caso contrário
Combinador:
F=λM.λn.if(isZero (predn)) then 1
else(multn(M(predn)))
Definição final: fact= YF
Nota:avaliação preguiçosa é requerida (Y diverge quando avaliado estritamente)
Funções de alta ordem
Em programação funcional, é comum termos funções que processam outras funções junto com os dados.
Funções que consomem ou retornam outras funções são chamadas
funções de alta ordem ou funcionais.
Os três funcionais clássicos em linguagens funcionais são map, filter e fold.
A funçãomapconsome uma função fe uma lista de valores l, e retorna a lista de resultados da aplicação def a cada elemento da listal. map succ (cons 3 (cons 1 empty)) =>
Funções de alta ordem (2)
A funçãofilterconsome um predicadop (função com retorno booleano) e uma lista de valoresl, e retorna a lista contendo os valores eml que satisfazem o predicado.
filter par (cons 3 (cons 2 (cons 1 empty))) => (cons 2 empty)
A funçãofold consome uma operação bináriaop, um valor inicialinite uma listal, e substitui cons porope empty por initem l, retornando um valor final.
fold + 0 (cons 3 (cons 2 (cons 1 empty))) => (+ 3 (+ 2 (+ 1 0)))
Universalidade de cálculo lambda
Universalidade
Cálculo-lambda como linguagem de programação é Turing-computável.
Há várias formas de provar isso, mas é fácil perceber que
● Usando duas listas podemos codificar uma fita bidirecional
● Podemos codificar estados e símbolos utilizando números
● Usando listas, pares, podemos codificar uma função de transição de estado
● Procedimentos recursivos pode ser utilizados para implementar consulta à função de transição de estado.
Conteúdo
Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução betaPropriedades da redução beta Programação em cálculo lambda
Booleanos Números naturais Pares ordenados Listas Definições locais Funções recursivas Funcões de alta ordem Revisão
Revisão
O que vimos:
● os componentes fundamentais da teoria de cálculo lambda.
● como utilizar o cálculo lambda puro como uma linguagem de programação
funcional, utilizando diversos mecanismos de codificação. O que não foi visto:
● a teoria de lambda calculi é vasta, e inclui diversas variações importantes com sistemas de tipos associados:
○ cálculo lambda simplesmente tipado
○ cálculo lambda polimórfico
○ cálculo lambda com tipos dependentes
● mesmo a teoria do cálculo lambda sem tipos possui diversos resultados que
Retomando a pergunta inicial …
Suponha uma linguagem de programação com números e valores booleanos. Considere as seguintes construções:
1. execução condicional (if-then e if-then-else)
2. laços de repetição (while e for)
3. definição de variáveis e operador de atribuição
4. definição e aplicação de funções
Pergunta:se fosse necessário escolher somente um dos itens acima, ainda teríamos uma linguagem de programação expressiva o suficiente?
Conteúdo
Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução betaPropriedades da redução beta Programação em cálculo lambda
Booleanos Números naturais Pares ordenados Listas Definições locais Funções recursivas Funcões de alta ordem Revisão
Referências
The lambda calculus: its syntax and semantics(Barendregt, 1984) An introduction to functional programming through lambda calculus(Michaelson, 1989)
Lectures on the Curry-Howard isomorphism(Sørensen and Urzyczyn, 2006)
A short introduction to the Lambda Calculus(Jung, 2004)
Disponível online emhttp://www.cs.bham.ac.uk/~axj/pub/
papers/lambda-calculus.pdf
How to Design Programs: An Introduction to Computing and Programming(Felleisen, Findler, Flatt, Krishnamurthi, 2003)