Cálculo
Lambda

Frank Coelho de Alcantara - 2021    

Visão Geral

Introduzido, nos anos 1930, por Alonzo Church. Estudo da computação por funções.

Equivalente a Máquina de Turing.

Notação minimalista: expõe apenas o que é necessário para computação com funções.

Duas operações essenciais: criação e aplicação.

Notação Tradicional

Uma abstração: abstração lambda: $$\lambda x.E$$

Representando uma função ($\lambda$) com argumento $x$ e corpo $E$. O $E$ chamado de termo $\lambda$ ou expressão $\lambda$. Ou ainda, de escopo da abstração.

As funções não possuem nomes. $\lambda$ é um signo, uma notação para indicar o início da definição de uma função.

Uma função que tem um parâmetro $x$ e retorna alguma coisa definida pelo corpo $E$.

Abstração lambda ou função anônima unária.

Funções Anônimas

O coração do cálculo lambda e da programação funcional são as funções anônimas.

  • C e Pascal: não
  • C++ : sim (a partir da versão C++11)
  • Javascript : sim
  • Python e Ruby : sim
  • C# : sim (a partir de versão 3.0)
  • Java : sim (a partir de versão 8)

E as linguagens funcionais, puras ou não: LISP, Scheme, Clojure, Scala, Ocaml, F#, Haskell, ... .

Cálculo

A medida que avançamos na álgebra podemos notar que a palavra cálculo representa um conjunto de regras que determinam como podemos mover símbolos ($x,y,z,...$) em uma página em busca de simplificação ou significado. Isto é válido para integrais, diferenciais, equações diferenciais, transformadas, etc..

O cálculo lambda está relacionado com definir e avaliar funções e é composto de uma linguagem e das regras de manipulação desta linguagem.

Entendendo Melhor

$f(x) = a$ escreve-se: $\lambda x.\space a$

$g(x)=x$ escreve-se: $\lambda x. \space x$

$f(x) = x^2+3x+1$ escreve-se: $(\lambda x.x^2+3x+1)$

No último exemplo leremos: a função que, dado o argumento $x$ calcula o valor de $x^2+3x+1$.

Não é necessário mas fica mais claro assim:$(\lambda x.\space (x^2+3x+1))$

Sintaxe BNF

expression ::= constante
| variable <=identificador
| expression expression <=aplicação
| $\lambda$ variable.expression <=abstração
| (expression) <=agrupamento

Constante: números ou funções prédefinidas.

Variable: identificadores como $x$ ou $y$.

Derivação

Considere: $\lambda x.((+\space 1)\space x)$:

expression $\Rightarrow$ $\lambda$ variable.expression
$\Rightarrow$ $\lambda x.$expression
$\Rightarrow$ $\lambda x.$(expression)
$\Rightarrow$ $\lambda x.$(expression expression)
$\Rightarrow$ $\lambda x.$((expression) expression)
$\Rightarrow$ $\lambda x.$((expression expression) expression)
$\Rightarrow$ $\lambda x.$((constante constante) expression)
$\Rightarrow$ $\lambda x.((+\space 1)$ expression)
$\Rightarrow$ $\lambda x.((+\space 1)$ variable)
$\Rightarrow$ $\lambda x.((+\space 1)\space x)$

Parênteses

Os parênteses são utilizados na aplicação e para eliminar qualquer ambiguidade na interpretação.

Mais claro $(\lambda x.((+\space 1)\space x))$ que $(\lambda x.\space +\space 1\space x)$

Lembre-se, ao colocar, ou retirar, parênteses que você está escrevendo para que outros leiam.

Se outra pessoa não conseguir entender a expressão que você escreveu, em alguns dias, você também não entenderá.

Constantes e variáveis

$x$,$y$,$2$,$4$ são expressões lambda válidas que podem ser representados pelas seguintes abstrações:

  1. $\lambda x.\space x$
  2. $\lambda y.\space y$
  3. $\lambda x.\space 2$
  4. $\lambda x.\space 4$

Também é possível escrever qualquer numero com abstrações lambda veja: Church Encoding.

Universalidade

Com o cálculo Lambda podemos definir:

  1. booleanos e condicionais
  2. aritmética
  3. estruturas de dados
  4. recursividade

O cálculo lambda é considerado "a menor linguagem de programação" e permite a criação de qualquer algoritmo. Dá tanto trabalho quanto o Assembly.

Aplicação

A operação básica do cáculo lambda é a aplicação de funções.

Considere: $\lambda x.((+\space 1)\space x)$

Podemos aplicar a esta função o valor 3: $\lambda x.((+\space 1)\space x)\space 3$

Neste caso estamos aplicando o valor 3 à função $\lambda x.((+\space 1)\space x)$

Logo: $$\lambda x.((+\space 1)\space x)\space 3 = (+\space 1\space 3) \Rightarrow 4$$

Só para reforçar, dizemos que aplicamos à função o valor 3. Historicamente chamamos este processo de beta-conversion ou beta-reduction.

Observe que não encontramos um resultado. Encontramos o significado da aplicação. Esta é a forma normal, ou $\beta$-normal.

Beta Conversion

Chamamos de beta-conversion, beta-reduction ou $\beta$-conversion ao processo de substituir uma variável ligada, no corpo da abstração lambda, pelo argumento passado pela aplicação desta função. O processo inverso, transformar uma expressão já reduzida novamente à abstração é chamado de $\beta$-abstraction.

De forma leiga, podemos dizer que a conversão beta é a aplicação da função ao seu argumento. Tome, por exemplo, a função $f_{(x)}= 3x+1$ quando aplicamos o valor 2 nesta função, teremos: $f_{(2)}= 3\times 2+1 = 7$. Isto é cálculo algébrico. O que fizemos foi aplicar (substituir) à função ao valor 2 substituindo a variável $x$, a variável da função (está ligada).

Aplicação

Para simplificar podemos escrever $\lambda x.((+\space 1)\space x)\space 3$ como $\lambda x.(x+1)\space 3$. Não está sintaticamente correto, mas simplifica;

Com isso temos a seguinte árvore sintática:

   
                   aplicação
                    /   \
                   λ     3
                  / \
                 x   +
                    / \
                   x   1
            

Duas Aplicações

Considere a função $(\lambda x.x+1)(\lambda y.y+2)\space 3$ neste caso teríamos:

Com isso temos a seguinte árvore sintática:

   aplicação =>   aplicação =>    aplicação =>  +  => 6
    /     \            /   \           /   \         / \
   λ     aplicação    λ     +         λ     5       5   1
  / \       /  \     / \   / \       / \
 x   +     λ    3   x   + 3   2     x   +
    / \   / \          / \             / \
   x   1 y   +        x   1           x   1
            / \                  
           y   2
          

Teste a si mesmo

Considere a função $(\lambda x.x+1)(\lambda y.y+2)\space 3$ E tente começar pela primeira função e escreva a árvore sintática:

Com isso temos a seguinte árvore sintática:

    aplicação      =>         +   =>    + =>  +  =>  6
    /     \                  / \       / \   / \
  λ     aplicação     aplicação 1     +   1 5   1
 / \       /  \          / \         / \
x   +     λ    3        λ   3       3   2
   / \   / \           / \     
  x   1 y   +         y   +    
           / \       / \
          y   2     y   2
           

Variáveis Ligadas

Uma variável $x$ qualquer, em uma expressão do cálculo lambda é dita ligada (bound) se esta variável for declarada como tal em uma determinada abstração lambda.

Para $\lambda x. (\times \space 2)\space x$, $x$ é a variável ligada.

Para $\lambda y. (+\space x)\space y$, $y$ é a variável ligada.

Todas a variáveis que eventualmente ocorram na abstração e que não estejam ligadas serão ditas livres. ou globais.

Ou seja: aplicando 2 a $\lambda y.(+\space x)\space y$ teremos $\lambda y.(+\space x)\space 2 \Rightarrow (+\space 2 \space x)$

Variáveis Ligadas, ou não?

A mesma variável $x$ pode aparecer em contextos diferentes na mesma abstração lambda. Em algumas instâncias esta variável pode estar ligada e livre em outras. Tome como exemplo: $$(\lambda x. \space+\space(\lambda y.((\lambda x. \times \space x\space y\space )\space 2)) \space x) \space y) $$

Observe que a variável $x$ após o $\times$ está em uma ligação diferente da variável $x$ mais externa.

Observe também que o primeiro $y$ está ligado e que o segundo é livre.

Combinadores

Uma abstração lambda sem variáveis livres são chamadas de combinadores, ou de expressões fechadas.

Combinadores são usados para combinar funções.

O menor combinador possível é a função identidade $I$ $$I \equiv \lambda x.\space x$$

A função identidade, quando avaliada tem o significado da própria variável. $$(\lambda x.\space x) 5 \Rightarrow 5$$

Exemplo 1 - $\beta$-reduction

Tomemos a função: $$((\lambda a.a) \lambda b. \lambda c. b)(x)\lambda e.f $$

$$(\lambda b. \lambda c.b) (x)\lambda e.f$$

$$(\lambda c.x) \lambda e.f $$

$$x$$

logo $x$ é a forma $beta$-normal de $((\lambda a.a) \lambda b. \lambda c. b)(x)\lambda e.f $

Exemplo 2 - $\beta$-reduction

Tomemos a função: $$(\lambda x. \space+\space(\lambda y.((\lambda x. \times \space x\space y\space )\space 2)) \space x) \space y) $$

Teremos: $$(\lambda x. \space+\space((\lambda y.(\times \space 2\space y\space )) \space x) \space y) $$

$$(\lambda x. \space+\space((\times \space 2\space x\space )) \space y) $$

$$(\lambda x. \space+\space(\times \space 2\space x\space ) \space y) $$

ou seja, a forma $\beta$-normal desta função é equivalente a forma algébrica: $(2x+y)$

Passando por valor

Passar por valor é um conceito comum em linguagens de programação imperativas. O equivalente em lambda calculus seria: $$(\lambda x.(\times \space x \space x)(+\space 2\space 3))$$

$$(\lambda x.(\times \space x\space x)\space 5)$$

$$(\times \space 5 \space 5) \Rightarrow 25$$

Ou seja, avaliamos as funções imediatamente passando o resultado para a próxima função.

Passando por referência

O nome correto é Lazy Evaluation. $$(\lambda x.(\times \space x \space x)(+\space 2\space 3))$$

$$(\lambda x.(\times \space (+\space 2\space 3)\space (+\space 2\space 3)))$$

$$(\times \space (+\space 2\space 3)\space (+\space 2\space 3))) \Rightarrow 25$$

Ou seja, passamos as funções para outra funções e só avaliamos no final.

Um problema Interessante

Considere:$$((\lambda x. \space x\space x)(\lambda x.\space x\space x))$$

$$((\lambda x.\space x\space x)(\lambda x.\space x\space x))$$

O que leva a uma recursão infinita.

Considere agora: $$((\lambda y. 2)(\lambda x. \space x\space x)(\lambda x.\space x\space x)))$$

Neste caso, passando por valor, continuamos com a indefinição provocada pela recursão. Mas, se passarmos por referência, o resultado é 2 já que não variável $y$ no corpo da função.

Exemplo 2 - Evaluation

Considere:$$(((\lambda f. (\lambda x. f\space (f\space x))) (\lambda y. (\times\space y\space y)))\space 3)$$

Muito difícil de ler... vamos mudar um pouco a notação:

$$\{(\lambda f. (\lambda x. f\space (f\space x))) (\lambda y. (\times\space y\space y))\space \} \space 3 $$

Quase deu... vamos tentar novamente:

$$\{[(\lambda x. (\lambda y. (\times\space y\space y)) \space ((\lambda y. (\times\space y\space y))\space x))] \space \} \space 3 $$

$$\{[(\lambda x. (\lambda y. (\times\space y\space y)) \space (\times\space x\space x)] \space \} \space 3 $$

$$\{[(\lambda x. (\times\space (\times\space x\space x) \space (\times\space x\space x)) \space ]\space \} \space 3 $$

$$\{[(\lambda x. (\times\space (\times\space 3\space 3) \space (\times\space 3\space 3)) \space ]\space \} \space $$

$$ (\times\space 9 \space 9) \Rightarrow 81$$

$\alpha$-Reduction

A técnica conhecida como $\alpha$-Reduction é o formalismo que nos permite mudar o nome de uma variável em uma abstração lambda.

  1. $(\lambda x. \space +\space x\space 1)$
  2. $(\lambda y.\space +\space y\space 1)$

As duas funções acima são equivalentes.

$$(\lambda x. \space +\space x\space 1) \Leftrightarrow_{\alpha} (\lambda y.\space +\space y\space 1)$$

Exercício 1

Aplique a técnica $\beta$-Reduction, o máximo possível às seguintes abstrações:

  1. $(\lambda z. \space z)(\lambda y. \space y\space y)(\lambda x. \space x\space a) $
  2. $(\lambda z. \space z)(\lambda z. \space z\space z)(\lambda z. \space z\space y) $
  3. $((\lambda x.((\lambda y.(x\space y))\space x))(\lambda z.\space w))$
  4. $(\lambda x.\space x\space x) (\lambda y.y\space x) z$
  5. $(((\lambda x. \lambda y.(x\space y))(\lambda y.y))\space w)$
  6. $(\lambda z.\space x)y$

Lembre-se que você sempre pode usar $\alpha$-Reduction.

Exercício 1-1

$(\lambda z.z)(\lambda y.y\space y)(\lambda x.x\space a)$

  1. $(\lambda y.y\space y)(\lambda x.x\space a)$
  2. $(\lambda x.x\space a)(\lambda x.x\space a)$
  3. $a \space a$

Exercício 1-3

$((\lambda x.((\lambda y.(x\space y))\space x))(\lambda z.\space w))$

  1. $((\lambda x.(x\space x))(\lambda z.\space w))$
  2. $((\lambda z.\space w)\space (\lambda z.\space w))$
  3. $w \space w$

Outra forma de resolver esta função incluiria a aplicação da $\alpha$-reduction.

Exercício 1-5

$(((\lambda x. \lambda y.(x\space y))(\lambda y.y))\space w)$

  1. $(((\lambda x. \lambda a.(x\space a))(\lambda y.y))\space w)$
  2. $((\lambda a.(\lambda y.y)a))\space w)$
  3. $(\lambda y.y)w$
  4. $w$

Exercício 1-Respostas

  1. $a\space a$
  2. $y \space y$
  3. $w \space w$
  4. $x\space x\space z$
  5. $w$
  6. $x$