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

Tamanho: px
Começar a partir da página:

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

Transcrição

1 Minicurso 1 Uma introdução ao cálculo lambda e a linguagens de programação funcionais Rodrigo Machado rma@infufrgsbr

2 2/68 Conteúdo Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução beta Propriedades 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

3 3/68 Conteúdo Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução beta Propriedades 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

4 4/68 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?

5 5/68 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? E se fosse possível escolher somente um dos itens acima?

6 Origem: notação lambda Considere a seguinte definição matemática: f(x) = x A igualdade acima está definindo uma função f, que consome um número e devolve um número f(3) = = 16 A igualdade acima está aplicando a definição de f a um valor específico O propósito original da notação lambda foi resolver a seguinte ambiguidade: f(e) = e Afinal, se trata da aplicação de f sobre a constante e = 2716 ou da definição de f? 6/68

7 7/68 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 = λxx Acima temos a definição da função O λx indica que x deve ser interpretado como um parâmetro formal, isto é, um nome temporário para o valor a ser recebido pela função f(3) = (λxx 2 + 7)(3) = Acima temos a aplicação da função f, definida anteriormente, ao valor 3 Note que o significado da aplicação é a substituição do parâmetro formal x pelo valor concreto 3

8 8/68 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

9 9/68 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 para saber utilizar de forma eficaz as novas linguagens de programação

10 10/68 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 30) 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,

11 11/68 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

12 12/68 Conteúdo Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução beta Propriedades 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

13 13/68 Sintaxe: pré-termos Começaremos definindo um conjunto Λ de pré-termos Considere um conjunto infinito (mas contável) de nomes (aka parâmetros, identificadores, variáveis) o qual chamaremos Var Vamos denotar os elementos de Var por x, y, z, Definição: o conjunto Λ é o menor conjunto tal que: 1 se x Var então x Λ (variáveis) 2 se M Λ e N Λ N) Λ (aplicação) 3 se x Var e M Λ então λxm Λ (abstração lambda) Notação: vamos utilizar simplesmente M N para N)

14 14/68 Sintaxe: exemplos Exemplos de elementos de Λ : x x y λxx λxy (λxx) y λx(x y) (λxx) (λxx) λxλyx λxλyy (λxy) Nota: precisamos de regras claras para evitar ambiguidade na escrita de um pré-termo Exemplo: λxx y representa λx(x y) ou (λxx) y?

15 Sintaxe: regras de notação 1 O λ engloba tudo à direita (o máximo possível) λxx y = λx(x y) (λxx) y x λy(λxx y)(z 2 O é associativo à esquerda x y z = (x y) z x (y z) x 3 Notação simplificada para λ s seguidos λx y zm = λxλyλzm x z w 15/68

16 16/68 Sintaxe: termos com nomes especiais Alguns pré-termos são famosos e possuem nomes especiais Combinadores (lógica combinatorial) I = λxx K = λx yx S = λx y z(x z (y z)) Auto-aplicação e ponto fixo ω = λxx x Ω = ω ω Y = λf (λx f(x x))(λx f(x x)) A utilidade desses termos será vista posteriormente

17 17/68 Variáveis livres e ligadas Definição: dentro do pré-termo λxm, dizemos que M é o escopo de λx Definição: uma ocorrência de x dentro do escopo de λx é dita ligada Caso contrário, x ocorre livre Exemplo: a) λxx y x é ligada, y é livre b) λxz λzz x z é livre, z e x são ligadas c) λxx λxx y x e x são ligadas, y é livre Nota: 1 Um mesmo nome por ter ocorrências ligadas e livres no mesmo pré-termo (b) 2 Uma ocorrência de x é sempre ligada ao λx mais interno (c)

18 Variáveis livres e ligadas (2) Ocorrências livres e ligadas de variáveis têm significados distintos: variáveis livres referem-se a nomes externos (globais) variáveis ligadas referem-se a parâmetros formais (locais) Nomes de variáveis livres são importantes: expressões distintas sin(π) 42 + π 2 sin(e) 42 + e 2 Nomes de parâmetros formais não são importantes: mesma definição λx sin(x) 42 + x 2 λe sin(e) 42 + e 2 18/68

19 19/68 Variáveis livres e ligadas (3) Definição: a função FV computa as variáveis que ocorrem livres em um pré-termo FV(x) = {x} FV(λxM) = FV(M) {x} FV(M N) = FV(M) FV(N) Definição: um pré-termo M onde FV(M) = {} é fechado, também chamado combinador Caso contrário, ele é aberto

20 20/68 Operação de substituição A operação de substituição M[x = N] substitui todas as ocorrências livres de x em M por N Exemplo: 1) (λxxy)[x = w] = λxxy 2) (λxxy)[y = w] = λxxw 3) (λxxy)[z = w] = λxxy 4) (zλzz)[z = w] = wλzz 5) (zz)[z = λzzz] = (λzzz)(λzzz) 6) (λxxy)[y = x] = (λxxx)? Pergunta: alguém nota algo estranho com a substituição 6?

21 21/68 Captura de variáveis livres Problema do Ex 6: captura de variáveis livres M N (λxxy) [y = x ] Considere M: na posição onde está y, o nome x é ligado Considere N: o nome x ocorre livre Ao substituir y por N, podemos colocar um x livre em uma posição onde o mesmo nome x está ligado Mas nomes livres e ligados possuem interpretações distintas, e isso altera o significado do termo Vamos querer evitar esse problema ao definirmos substituição

22 Operação de substituição: definição formal Definição: operação de substituição evitando captura de variáveis livres x[y = P] = { P x se x = y caso contrário (λxm)[y = P] = { λxm λx(m[y = P]) se x = y se x y e x FV(P) (M N)[y = P] = M[y = P] N[y = P] Pergunta: segundo esta definição, qual o resultado de (λxxy)[y = x]? Resposta: indefinido! 22/68

23 23/68 Equivalência alfa Definição: dois pré-termos M e N são α-equivalentes (M = α N) sss eles diferem somente na escolha dos nomes de variáveis ligadas Exemplo: λxxy = α λzzy λxxx = α λzzz λxxy α λyyy λyzy α λyxy O conceito de α-equivalência captura a intuição que a escolha dos nomes dos parâmetros formais realmente não é importante

24 24/68 Equivalência alfa: definição formal Definição: = α é a menor relação de equivalência sobre Λ tal que y FV(M) λxm = α λy(m[x = y]) (α) M = α M N M = α N M M = α M M N = α M N M = α M λxm = α λxm

25 25/68 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é-termo M Exemplo: {λxx} α = { λxx, λyy, λzz, } {λxx y} α = { λaa y, λbb y, } Definição: Λ é conjunto de todos os termos lambda: Λ = Λ = α

26 26/68 Termos lamba: operação de substituição Operações definidas em Λ podem ser estendidas para Λ Lembre: Porém, como e (λxxy)[y = x] indefinido λxxy = α λaay (λaay)[y = x] = λaax podemos estender M[x = N] para termos, obtendo {λxxy} α [y = {x} α ] = {λaax} α Efeito: temos em Λ uma operação de substituição que é total e bem-definida (evita captura de variáveis livres)

27 27/68 Termos vs pré-termos No que segue, vamos falar de termos e não mais de pré-termos Contudo, vamos escrever termos usando M ao 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 A principal justificativa é reduzir a poluição excessiva da notação

28 28/68 Redexes e formas normais Definição: um redex (reducible expression) é um subtermo de M com o formato (λxp) 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(λxy x)((λyx) y) contém dois redexes b) λxλy x x é uma forma normal

29 29/68 Redução beta Redução beta descreve a avaliação de termos lambda através de substituição Temos M β N se obtivermos N através da contração de um redex de M Exemplo: (λzλxx z) y β λy(λxy x) ((λyx) y) β λy(λxy x) x β λxx y λy(λxy x) x λyy x

30 30/68 Redução beta: definição formal Definição: β é a menor relação em Λ tal que (λxp) Q β P[x = Q] (β) M β M N M β N M M β M λxm β λxm M β M M N β M N Definição: β é o fecho transitivo e reflexivo de β Intuitivamente, M N quando M reduz para N em 0 ou mais passos de redução beta

31 31/68 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λxx z) y N = (λuλxx y) (t t) P = λxx y Nota: perceba que M / β N e N / β M

32 32/68 Equivalência beta: possuir forma normal Definição: dizemos que um termo M possui forma normal sss M = β N e N é uma forma normal Exemplo: (λxx x) possui forma normal (ele é fn) (λxx x) a possui forma normal (ele β-reduz para (a a), que é fn) (λxx x) (λxx x) não possui forma normal (ele β-reduz para si mesmo)

33 33/68 Estratégias de avaliação Um termo P pode ter diversos redexes e, portanto, avaliar para distintos termos Exemplo: (considere ω = λxx x e I β ω I I I ω I ω I

34 34/68 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 Ω) β (λyi) Ω β I strict: (true I Ω) β (λyi) Ω β (λyi) Ω β

35 35/68 Propriedades de redução beta: confluência Confluência: (Church-Rosser) se N β M β N então existe P tal que N β P β N Corolário: formas normais são únicas Exemplo: ω(ii) ω(i) (II)(II) I(II) II

36 36/68 Propriedades de redução beta: normalização Normalização: se o termo M possui forma normal N, então avaliar M 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

37 37/68 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) redução δ (tipos de dados e operações primitivas)

38 38/68 Conteúdo Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução beta Propriedades 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

39 39/68 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

40 40/68 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 Nota: nessas codificações o foco não é eficiência!

41 41/68 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

42 42/68 Construção condicional Definição: construção if-then-else : if a then b else c = λ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 Exercício: definir as operações booleanas not, and e or

43 43/68 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) )) Também referenciados por c n, para n N

44 44/68 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 n com estrutura n = λf x f (f (f x) ) 2 o resultado deve ter p e q ligados por lambdas: λp q 3 o termo (n p q) muda os f s em p s, e o x em q 4 por último, introduzimos um p adicional ao número

45 45/68 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 (λxfalse) true Nota: a função predecessor é trabalhosa e será vista posteriormente

46 46/68 Pares ordenados Definição: um par (M, N) pode ser representado por pair M N onde pair = λ m n b b m n Exemplo: pair 0 true = λb b 0 true Definição: funções de acesso ao conteúdo de um par fst = λp p true snd = λp p false Notação: usaremos M, N como um sinônimo para pair M N

47 47/68 Pares ordenados: predecessor Usando pares podemos definir pred N N onde pred(n) = Função auxiliar: shiftinc(a, b) = (b, b + 1) 0 se n 1 n 1 caso contrário shiftinc = λp snd p, succ (snd p) Definição: o termo pred abaixo implementa a função pred pred = λnfst (n shiftinc 0, 0 )

48 48/68 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) (cons 2 (cons 5 (cons 1 empty)))

49 49/68 Listas (2) Três funções são definidas para acessar o conteúdo da lista: isempty testa 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

50 50/68 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 = λll (λx λyfalse) head = fst tail = snd

51 51/68 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: def a = v in p = (λap) v

52 52/68 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ção I que recebe um número n uma função f um valor inicial x para o qual (I n f x) resulta em n f (f (f (f x) ))

53 53/68 Funções recursivas (2) Tentativa inicial: Ideia da construção: I = λ n f x if (iszero n) then x else (I (pred n) f (f x)) se n = 0 : retorna x se n > 0 : itera (n 1) vezes a função f no argumento (f x) Problemas: não há memória para armazenar a definição de I definição circular qual o termo lambda que codifica I?

54 54/68 Funções recursivas (3) Imagine o lado direito da equação como a aplicação de um combinador S sobre I Nesse caso a equação I = λ n f x if (iszero n) then x else (I (pred n) f (f x)) se torna onde I = S I S = λ X λ n f x if (iszero n) then x else (X (pred n) f (f x)) Nota: veja que a definição de S não é circular! Outra visão do problema: achar um termo I que é o ponto fixo de S

55 55/68 Pontos fixos Definição: o ponto fixo (fixed-point, FP) de uma função f X X é um elemento x X tal que f(x) = x Exemplo: 1) x x 2 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 para S Λ Λ Boas novas! há um termo que nos constrói o ponto fixo!

56 56/68 Pontos fixos: combinador Y Chamamos o termo abaixo de combinador Y (ou combinador de ponto fixo) Y = λf(λxf(x x))(λxf(x x)) Teorema: o combinador Y produz um ponto fixo para seu argumento Demonstração: YS (λxs(x x)) (λxs(x x)) S (λxs(x x)) (λxs(x x)) S(YS) β β = β YS = β S(YS) e, portanto, YS é um ponto fixo de S Podemos finalmente definir I = YS

57 Pontos fixos: combinador Y em Y λx x x @ x x x x 57/68

58 58/68 Pontos fixos: combinador Y em ação (2) se S = β λ X (iszero n) λ n f x x if X (pred n) f (f x)

59 59/68 Pontos fixos: combinador Y em ação (3) então (Y S) = β (iszero n) x λ n f x if (iszero (pred n)) (f x) if if (iszero (pred (pred n))) (f (f x))

60 Funções recursivas e operador Y Usando Y podemos codificar funções como termos nos baseando em suas definições recursivas Definição recursiva: Combinador: fact(n) = 1 se n 1 n fact(n 1) caso contrário F = λmλnif (iszero (pred n)) then 1 else (mult n (M (pred n))) Definição final: fact = YF Nota: avaliação preguiçosa é requerida (Y diverge quando avaliado estritamente) 60/68

61 61/68 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ção map consome uma função f e uma lista de valores l, e retorna a lista de resultados da aplicação de f a cada elemento da lista l map succ (cons 3 (cons 1 empty)) => (cons 4 (cons 2 empty))

62 62/68 Funções de alta ordem (2) A função filter consome um predicado p (função com retorno booleano) e uma lista de valores l, e retorna a lista contendo os valores em l que satisfazem o predicado filter par (cons 3 (cons 2 (cons 1 empty))) => (cons 2 empty) A função fold consome uma operação binária op, um valor inicial init e uma lista l, e substitui cons por op e empty por init em l, retornando um valor final fold + 0 (cons 3 (cons 2 (cons 1 empty))) => (+ 3 (+ 2 (+ 1 0))) Exercício: defina map, filter e fold em cálculo lambda

63 63/68 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 Com esses componentes, podemos codificar Máquinas de Turing

64 64/68 Conteúdo Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução beta Propriedades 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

65 65/68 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 não foram citados Para mais informações, ver as referências ao final

66 66/68 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? Resposta: certamente, desde que a escolha seja o item 4!

67 67/68 Conteúdo Ideias iniciais Cálculo lambda Sintaxe Operação de substituição Equivalência alfa Redução beta Propriedades 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

68 68/68 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 em papers/lambda-calculuspdf How to Design Programs: An Introduction to Computing and Programming (Felleisen, Findler, Flatt, Krishnamurthi, 2003) Disponível online em

Cálculo Lambda Sem Tipos

Cálculo Lambda Sem Tipos 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

Leia mais

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

Programação Funcional - Introdução a Cálculo Lambda Programação Funcional - Introdução a Cálculo Lambda Cristiano Damiani Vasconcellos Universidade do Estado de Santa Catarina 1. Definição Cálculo lambda (λ-cálculo) é um modelo matemático capaz de ilustrar

Leia mais

O Cálculo λ sem Tipos

O Cálculo λ sem Tipos Capítulo 2 O Cálculo λ sem Tipos 21 Síntaxe e Redução Por volta de 1930 o cálculo lambda sem tipos foi introduzido como uma fundação para a lógica e a matemática Embora este objectivo não tenha sido cumprido

Leia mais

Centro Universitário do Triângulo

Centro Universitário do Triângulo 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

Leia mais

Linguagens de Programação Funcional

Linguagens de Programação Funcional Linguagens de Programação Funcional Conceitos de Linguagens de Programação Pedro Libório Setembro de 2013 2 Roteiro Introdução Funções matemáticas Fundamentos das linguagens de programação funcionais A

Leia mais

Introdução ao cálculo-λ

Introdução ao cálculo-λ 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

Leia mais

Programação Funcional Cálculo Lambda - Aula Nº 3

Programação Funcional Cálculo Lambda - Aula Nº 3 Programação Funcional Cálculo Lambda - Aula Nº 3 2.3. Ordem de Redução Se uma expressão não contém mais redexes, então a avaliação está completa. Um expressão nesta forma é dita estar na forma normal.

Leia mais

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

Lambda Cálculo e Programação Funcional. Programação Funcional Bacharelado em Sistemas de Informação Maio Lambda Cálculo e Programação Funcional Programação Funcional Bacharelado em Sistemas de Informação Maio - 2009 Alonzo Church (1903 1995) Professor em Princeton, EUA (1929 1967) e UCLA (1967 1990) Inventou

Leia mais

Introdução à Programação Funcional

Introdução à Programação Funcional Introdução à Programação Funcional PPGIA - PUCPR Prof. Fabrício Enembreck 1 Conteúdo Introdução ao Cálculo Lambda e à Programação Funcional Introdução ao LISP e ao CLisp Funções Lambda e binding Funções

Leia mais

Fundamentos de Cálculo Lambda

Fundamentos de Cálculo Lambda Instituto Superior Técnico Universidade Técnica de Lisboa Lisboa, 2 de Novembro de 2006 Índice Introdução Aplicação e Abstracção Axiomática Aplicação Introdução Aplicação e Abstracção Axiomática FA F é

Leia mais

Funções Recursivas. Prof.: Edson Holanda Teoria da computação - Diverio e Menezes

Funções Recursivas. Prof.: Edson Holanda Teoria da computação - Diverio e Menezes Funções Recursivas Prof.: Edson Holanda [email protected] Teoria da computação - Diverio e Menezes Tipos de Formalismos Operacional Define-se uma máquina abstrata, baseada em estados, em instruções

Leia mais

Conceitos de Linguagem de Programação - 2

Conceitos de Linguagem de Programação - 2 Conceitos de Linguagem de Programação - 2 Arthur Jovita Guerra Thalles Santos Silva Universidade Estadual de Santa Cruz - Ilhéus, BA 1 de novembro de 2011 1 Revisão Natureza das linguagens de Programação

Leia mais

Matemática Discreta para Ciência da Computação

Matemática Discreta para Ciência da Computação Matemática Discreta para Ciência da Computação P. Blauth Menezes [email protected] Departamento de Informática Teórica Instituto de Informática / UFRGS Matemática Discreta para Ciência da Computação

Leia mais

Principais paradigmas de programação. Programação imperativa Programação funcional Programação lógica Programação OO

Principais paradigmas de programação. Programação imperativa Programação funcional Programação lógica Programação OO Principais paradigmas de programação Programação imperativa Programação funcional Programação lógica Programação OO Programação Imperativa É o paradigma mais usado. Programas são definidos através de sequências

Leia mais

Língua Natural EXERCÍCIOS RESOLVIDOS

Língua Natural EXERCÍCIOS RESOLVIDOS Mestrado em Engenharia Informática e de Computadores Língua Natural EXERCÍCIOS RESOLVIDOS (Linguagem Lambda) 3ª Edição Nuno Mamede Maio 2010 Departamento de Engenharia Informática Instituto Superior Técnico

Leia mais

ao paradigma imperativo

ao paradigma imperativo PARADIGMA FUNCIONAL PARADIGMA FUNCIONAL: INTRODUÇÃO G Exemplos de linguagens funcionais LISP - Início: LP puramente funcional - Depois: acréscimo de alguns recursos imperativos (aumentaram eficiência de

Leia mais

Expressões e sentença de atribuição

Expressões e sentença de atribuição Expressões e sentença de atribuição Marco A L Barbosa malbarbo.pro.br Departamento de Informática Universidade Estadual de Maringá cba Este trabalho está licenciado com uma Licença Creative Commons - Atribuição-CompartilhaIgual

Leia mais

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

Pedro Vasconcelos DCC/FCUP. Programação Funcional 3 a Aula Definição de funções Programação Funcional 3 a Aula Definição de funções Pedro Vasconcelos DCC/FCUP 2014 Definição de funções Podemos definir novas funções simples usando funções pré-definidas. minuscula :: Char -> Bool minuscula

Leia mais

Marcos Castilho. DInf/UFPR. 16 de maio de 2019

Marcos Castilho. DInf/UFPR. 16 de maio de 2019 16 de maio de 2019 Motivação Quais são os limites da computação? O que é um Problema de decisão? Um problema de decisão é um conjunto de perguntas, cada uma das quais tem um SIM ou um NÃO como resposta.

Leia mais

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

Nelma Moreira. Departamento de Ciência de Computadores da FCUP. Aula 12 Fundamentos de Linguagens de Programação Nelma Moreira Departamento de Ciência de Computadores da FCUP Fundamentos de Linguagens de Programação Aula 12 Nelma Moreira (DCC-FC) Fundamentos de Linguagens

Leia mais

Linguagem Haskell. Universidade Estadual Santa Cruz Conceitos de Linguagens de Programação. Tiago Carneiro 19 Agosto 2013

Linguagem Haskell. Universidade Estadual Santa Cruz Conceitos de Linguagens de Programação. Tiago Carneiro 19 Agosto 2013 Linguagem Haskell Universidade Estadual Santa Cruz Conceitos de Linguagens de Programação Tiago Carneiro 19 Agosto 2013 1 1 Linguagem Haskell Linguagem de programação funcional É um paradigma de programação

Leia mais

Aula prática 14. Expressão Lambda

Aula prática 14. Expressão Lambda Programação Funcional UFOP DECOM 2014.1 Aula prática 14 Expressão Lambda Sumário Resumo Expressões lambdas são funções anônimas que podem ser usadas como qualquer outro valor de primeira classe. Nesta

Leia mais

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

Expressões Lambda. Programação Funcional. Capítulo 7. José Romildo Malaquias Departamento de Computação Universidade Federal de Ouro Preto Programação Funcional Capítulo 7 Expressões Lambda José Romildo Malaquias Departamento de Computação Universidade Federal de Ouro Preto 2012.1 1/64 1 Valores de primeira classe 2 Expressão lambda 3 Aplicação

Leia mais

Lógica de Hoare. Abordagem que usaremos: aplicar o método de Hoare sobre uma linguagem de programação imperativa simplificada.

Lógica de Hoare. Abordagem que usaremos: aplicar o método de Hoare sobre uma linguagem de programação imperativa simplificada. Lógica de Hoare Método axiomático para provar que determinados programas são corretos. Introduzido em 1969 por Charles Antony Richard Hoare. Também utilizado para especificar a semântica de linguagens

Leia mais

SEMÂNTICA. Rogério Rocha. rode = program simples = var x : int := 3 in x := x + 5 end.

SEMÂNTICA. Rogério Rocha. rode = program simples = var x : int := 3 in x := x + 5 end. SEMÂNTICA program simples = var x : int := 3 in x := x + 5 end. rode =? Rogério Rocha Roteiro Introdução Sintaxe Semântica Dinâmica (Métodos formais) Operacional Axiomática Denotacional Estática Conclusão

Leia mais

Programação Funcional Aulas 5 & 6

Programação Funcional Aulas 5 & 6 Programação Funcional Aulas 5 & 6 Sandra Alves DCC/FCUP 2016/17 Definições usando outras funções Podemos definir funções usando outras previamente definidas (por exemplo: do prelúdio-padrão). Exemplo:

Leia mais

Linguagem de Programação e Compiladores

Linguagem de Programação e Compiladores Linguagem de Programação e Compiladores Fernando Antônio Asevedo Nóbrega Instituto de Ciências Matemáticas e de Computação USP SCC-206 Introdução à Compilação 24 de abril de 2012 1 / 20 Sumário 1 Introdução

Leia mais

Introdução Maquinas de Turing universais O problema da parada. Indecidibilidade. Rodrigo Gabriel Ferreira Soares DEINFO - UFRPE.

Introdução Maquinas de Turing universais O problema da parada. Indecidibilidade. Rodrigo Gabriel Ferreira Soares DEINFO - UFRPE. DEINFO - UFRPE Julho, 2014 Motivação Introdução O que pode ser computado? E mais intrigantemente, o que não pode ser computado? Motivação Introdução O que pode ser computado? E mais intrigantemente, o

Leia mais

Teoria da Computação Ficha de exercícios

Teoria da Computação Ficha de exercícios Teoria da Computação Ficha de exercícios Simão Melo de Sousa Ano lectivo 2004/2005 1 Conjuntos, Relações, Ordens e Conjuntos ordenados Exercício 1 Considere o conjunto Sal dos ordenados duma empresa X.

Leia mais

Capítulo 8: O problema da parada. Decidibilidade e computabilidade. José Lucas Rangel Introdução.

Capítulo 8: O problema da parada. Decidibilidade e computabilidade. José Lucas Rangel Introdução. Capítulo 8: O problema da parada. Decidibilidade e computabilidade. José Lucas Rangel 8.1 - Introdução. Como observado no capítulo anterior, podemos substituir a definição informal de procedimento pela

Leia mais

2.2. A Semântica Operacional do Cálculo Lambda

2.2. A Semântica Operacional do Cálculo Lambda 2.2. A Semântica Operacional do Cálculo Lambda Até agora foi descrita a sintaxe do cálculocomo calcular com ele.. Para chamá-lo de cálculo, devemos porém dizer Basicamente isto é realizado através de três

Leia mais

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

Procedimentos e Algorítmos Programas e Linguagens de Programação Tese de Church-Turing Formas de Representação de Linguagens Procedimentos e Algorítmos Programas e Linguagens de Programação Tese de Church-Turing Formas de Representação de Linguagens 1 Introdução Estudar computação do ponto de vista teórico é sinônimo de caracterizar

Leia mais

Linguagens de Programação Programação Funcional (Haskell)

Linguagens de Programação Programação Funcional (Haskell) Linguagens de Programação Programação Funcional (Haskell) Andrei Rimsa Álvares Sumário Introdução Programação funcional Linguagens funcionais Haskell Casamento de padrões Funções de ordem superior Avaliação

Leia mais

Primeira Prova de Linguagens de Programação - DCC024 - Sistemas de Informação

Primeira Prova de Linguagens de Programação - DCC024 - Sistemas de Informação Primeira Prova de Linguagens de Programação - DCC024 - Sistemas de Informação Nome: Eu dou minha palavra de honra que não trapacearei neste exame. Número de matrícula: As regras do jogo: A prova é sem

Leia mais

Programação Funcional

Programação Funcional Programação Funcional Lucília Camarão de Figueiredo Universidade Federal de Ouro Preto [email protected] Aula 04: Definição de funções 1 DEFINIÇÃO DE FUNÇÕES f x1 x2...xn = E Define uma função f de tipo

Leia mais

Primeira Prova de Linguagens de Programação - DCC024 -

Primeira Prova de Linguagens de Programação - DCC024 - Primeira Prova de Linguagens de Programação - DCC024 - Ciência da Computação Nome: Eu dou minha palavra de honra que não trapacearei neste exame. Número de matrícula: As regras do jogo: A prova é sem consulta.

Leia mais

Juliana Kaizer Vizzotto. Universidade Federal de Santa Maria. Disciplina de Teoria da Computação

Juliana Kaizer Vizzotto. Universidade Federal de Santa Maria. Disciplina de Teoria da Computação Universidade Federal de Santa Maria Disciplina de Teoria da Computação Quais são as capacidades e limitações fundamentais dos computadores? Funções Computáveis Algoritmo: descrição finitade uma computação

Leia mais

Programação de Computadores

Programação de Computadores Programação de Computadores Instituto de Computação UFF Departamento de Ciência da Computação Otton Teixeira da Silveira Filho Conteúdo Alguns Conceitos sobre Linguagens Paradigmas para linguagens de Programação

Leia mais

Capítulo 7. Expressões e Sentenças de Atribuição

Capítulo 7. Expressões e Sentenças de Atribuição Capítulo 7 Expressões e Sentenças de Atribuição Introdução Expressões são os meios fundamentais de especificar computações em uma linguagem de programação Para entender a avaliação de expressões, é necessário

Leia mais

Conceitos de Linguagens de Programação - Características. Paavo Soeiro

Conceitos de Linguagens de Programação - Características. Paavo Soeiro Conceitos de Linguagens de Programação - Características Paavo Soeiro Motivação Para que possa escolher uma linguagem apropriada ao problema. Melhorar o entendimento da linguagem utilizada. Facilitar o

Leia mais

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

Linguagens de Programação. Programação Funcional. Carlos Bazilio Linguagens de Programação Programação Funcional Carlos Bazilio [email protected] http://www.ic.uff.br/~bazilio/cursos/lp Funções como Valores de 1a. Classe Atribuição a Variáveis a = f() g = f

Leia mais

UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO. Prof.ª Danielle Casillo

UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO. Prof.ª Danielle Casillo UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO TEORIA DA COMPUTAÇÃO Aula 08 Equivalência de programas Parte 2 Prof.ª Danielle Casillo Poder computacional dos diversos tipos de programas

Leia mais

Programação de Computadores

Programação de Computadores Programação de Computadores Instituto de Computação UFF Departamento de Ciência da Computação Otton Teixeira da Silveira Filho Conteúdo Alguns Conceitos sobre Conceito de Algoritmo Pseudocódigo Tipos de

Leia mais

Linguagem Funcional Haskell

Linguagem Funcional Haskell Bacharelado em Ciência da Computação PARADIGMAS DE PROGRAMAÇÃO Linguagem Funcional Haskell Prof. Claudinei Dias email: [email protected] Principais Linguagens Funcionais LISP (John McCarthy,

Leia mais

Paradigmas. Fortran, Algol, Algol-68, Pascal, C, Cobol, PL/I

Paradigmas. Fortran, Algol, Algol-68, Pascal, C, Cobol, PL/I Paradigmas Paradigmas Tradicional Fortran, Algol, Algol-68, Pascal, C, Cobol, PL/I Paradigmas Tradicional Fortran, Algol, Algol-68, Pascal, C, Cobol, PL/I OO Simula-67, Smalltalk, C++, Eiffel, Object Pascal,

Leia mais

INE5403 FUNDAMENTOS DE MATEMÁTICA DISCRETA

INE5403 FUNDAMENTOS DE MATEMÁTICA DISCRETA INE5403 FUNDAMENTOS DE MATEMÁTICA DISCRETA PARA A COMPUTAÇÃO PROF. DANIEL S. FREITAS UFSC - CTC - INE Prof. Daniel S. Freitas - UFSC/CTC/INE/2007 p.1/30 3 - INDUÇÃO E RECURSÃO 3.1) Indução Matemática 3.2)

Leia mais

UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO. Prof.ª Danielle Casillo

UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO. Prof.ª Danielle Casillo UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO Prof.ª Danielle Casillo Diferentes computadores podem ter diferentes arquiteturas e os diversos tipos de linguagem de programação.

Leia mais

Computação Eletrônica. Tipos de dados, constantes, variáveis, operadores e expressões. Prof: Luciano Barbosa

Computação Eletrônica. Tipos de dados, constantes, variáveis, operadores e expressões. Prof: Luciano Barbosa Computação Eletrônica Tipos de dados, constantes, variáveis, operadores e expressões Prof: Luciano Barbosa Site da disciplina: www.cin.ufpe.br/~if165/ Recapitulando num cubo = n * n * n cubo Algoritmo

Leia mais

Introdução ao Curso. Área de Teoria DCC/UFMG 2019/01. Introdução à Lógica Computacional Introdução ao Curso Área de Teoria DCC/UFMG /01 1 / 22

Introdução ao Curso. Área de Teoria DCC/UFMG 2019/01. Introdução à Lógica Computacional Introdução ao Curso Área de Teoria DCC/UFMG /01 1 / 22 Introdução ao Curso Área de Teoria DCC/UFMG Introdução à Lógica Computacional 2019/01 Introdução à Lógica Computacional Introdução ao Curso Área de Teoria DCC/UFMG - 2019/01 1 / 22 Introdução: O que é

Leia mais

Fundamentos 1. Lógica de Predicados

Fundamentos 1. Lógica de Predicados Fundamentos 1 Lógica de Predicados Predicados e Quantificadores Estudamos até agora a lógica proposicional Predicados e Quantificadores Estudamos até agora a lógica proposicional A lógica proposicional

Leia mais

PROGRAMAÇÃO ESTRUTURADA E ORIENTADA A OBJETOS

PROGRAMAÇÃO ESTRUTURADA E ORIENTADA A OBJETOS INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA DO RIO GRANDE DO NORTE PROGRAMAÇÃO ESTRUTURADA E ORIENTADA A OBJETOS Docente: Éberton da Silva Marinho e-mail: [email protected] [email protected]

Leia mais

Introdução a Programação

Introdução a Programação Introdução a Programação Prof. André Gustavo Duarte de Almeida [email protected] docente.ifrn.edu.br/andrealmeida Aula 02 Primeiro Programa Roteiro Primeiros Passos Variáveis Expressões Comandos

Leia mais

Programação imperativa

Programação imperativa Capítulo 8 Programação imperativa 8.1 Exercícios de revisão 1. Distinga entre programação imperativa e programação funcional. 2. Explique a necessidade da introdução do operador de atribuição. 3. Diga

Leia mais

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

Listas em Haskell. Listas. Linguagem Haskell. Maria Adriana Vidigal de Lima. Faculdade de Computação - UFU. Setembro em Haskell Linguagem Haskell Faculdade de Computação - UFU Setembro - 2009 em Haskell 1 em Haskell Noções sobre Construção de por Compreensão Funções Sobre Processamento de Fundamentos em Haskell Noções

Leia mais

Análise de Algoritmos Estrutura de Dados II

Análise de Algoritmos Estrutura de Dados II Centro de Ciências Exatas, Naturais e de Saúde Departamento de Computação Análise de Algoritmos Estrutura de Dados II COM10078 - Estrutura de Dados II Prof. Marcelo Otone Aguiar [email protected]

Leia mais

Prof. Leonardo Augusto Casillo

Prof. Leonardo Augusto Casillo UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO Aula 6 Álgebra de Boole Prof. Leonardo Augusto Casillo Álgebra de Boole (ou Boleana) Desenvolvida pelo matemático britânico George

Leia mais

Aula 10: Decidibilidade

Aula 10: Decidibilidade Teoria da Computação Aula 10: Decidibilidade DAINF-UTFPR Prof. Ricardo Dutra da Silva Definição 10.1. Um problema de decisão P é um conjunto de questões para as quais as respostas são sim ou não. Exemplo

Leia mais

Capítulo 9: Linguagens sensíveis ao contexto e autômatos linearmente limitados.

Capítulo 9: Linguagens sensíveis ao contexto e autômatos linearmente limitados. Capítulo 9: Linguagens sensíveis ao contexto e autômatos linearmente limitados. José Lucas Rangel 9.1 - Introdução. Como já vimos anteriormente, a classe das linguagens sensíveis ao contexto (lsc) é uma

Leia mais

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

Pedro Vasconcelos DCC/FCUP. Programação Funcional 5 a Aula Definições recursivas Programação Funcional 5 a Aula Definições recursivas Pedro Vasconcelos DCC/FCUP 2014 Definições usando outras funções Podemos definir funções usando outras previamente definidas (e.g. do prelúdio-padrão).

Leia mais

Capítulo 2: Procedimentos e algoritmos

Capítulo 2: Procedimentos e algoritmos Capítulo 2: Procedimentos e algoritmos Para estudar o processo de computação de um ponto de vista teórico, com a finalidade de caracterizar o que é ou não é computável, é necessário introduzir um modelo

Leia mais

SEMÂNTICA 02/09/2013. Conceitos de LPs - Semântica

SEMÂNTICA 02/09/2013. Conceitos de LPs - Semântica UNIVERSIDADE ESTADUAL DE SANTA CRUZ CURSO: CIÊNCIA DA COMPUTAÇÃO DISCIPLINA: CONCEITOS DE LINGUAGENS DE PROGRAMAÇÃO DOCENTE: ROGÉRIO VARGAS DISCENTE: MARIANNA NOVAES Semântica SEMÂNTICA Semântica é a área

Leia mais