PROGRAMAÇÃO FUNCIONAL NOTAS DE AULAS

Documentos relacionados
Aula prática 5. Funções Recursivas

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

Cálculo Lambda Sem Tipos

Linguagens de Programação Funcional

Paradigmas de Programação

Implementação de Linguagens

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

Paradigmas de Programação

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

Redução de grafos. Pedro Vasconcelos. 4 de Março de 2014

PROGRAMAÇÃO de COMPUTADORES: LINGUAGEM FORTRAN 90/95

Introdução a Algoritmos Parte 08

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

Linguagens de Programação. Programação Funcional e Haskell Declarando Tipos Thiago Alves

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

Linguagem Funcional Haskell

Linguagens de Programação

Exercícios: Árvores. Universidade Federal de Uberlândia - UFU Faculdade de Computação - FACOM Lista de exercícios de estrutura de dados em linguagem C

Trabalho Linguagem e Programação de Compiladores

Fundamentos de Programação

Compiladores - Especificando Sintaxe

A máquina SECD. Pedro Vasconcelos. 20 de Fevereiro de 2014

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

Recursividade. Métodos iterativos. Prof. Cesar Augusto Tacla. Métodos iterativos utilizam estruturas de repetição

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

Professor: Domingos Equipe Haskell: Lucas Montesuma, Francisco Leonardo CONCEITOS DA LINGUAGEM DE PROGRAMAÇÃO CÁLCULADORA EM HASKELL

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

Programação Funcional 9 a Aula Programas interativos

CP Compiladores I Prof. Msc.. Carlos de Salles

Programação Funcional. Capítulo 21. Parsers. José Romildo Malaquias. Departamento de Computação Universidade Federal de Ouro Preto 2018.

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

puras um ou mais apenas mesmos

Expressões Condicionais

ao paradigma imperativo

04 Recursão SCC201/501 - Introdução à Ciência de Computação II

Árvores. Thiago Martins, Fabio Gagliardi Cozman. PMR2300 / PMR3201 Escola Politécnica da Universidade de São Paulo

Programação Funcional Aulas 5 & 6

Árvores. Thiago Martins, Fabio Gagliardi Cozman. PMR2300 / PMR3201 Escola Politécnica da Universidade de São Paulo

Tratamento dos Erros de Sintaxe. Adriano Maranhão

Programação imperativa

Capítulo 8: Abstrações de dados

INE Programação Funcional - Transparência Resolução de alguns problemas de redução:

Paradigmas de Programação

Pedro Vasconcelos DCC/FCUP. Programação Funcional 17 a Aula Tipos abstratos

Linguagens de Programação

Implementação de Linguagens

Linguagens de Programação Aula 14

Computação II Orientação a Objetos

USANDO UM MÉTODO INDUTIVO PARA RESOLVER PROBLEMAS. Bruno Maffeo Departamento de Informática PUC-Rio

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

Prof. A. G. Silva. 25 de setembro de Prof. A. G. Silva INE5603 Introdução à POO 25 de setembro de / 35

Nomes, vinculações e escopos

Árvores. Fabio Gagliardi Cozman. PMR2300 Escola Politécnica da Universidade de São Paulo

Universidade de São Paulo

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

FACULDADE BATISTA MINEIRA - CST Banco de Dados Estruturas de Dados - Variáveis

SCC Capítulo 2 Recursão

Informática Parte 15 Prof. Márcio Hunecke

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

Expressão Condicional

V.2 Especificação Sintática de Linguagens de Programação

CAP. VI ANÁLISE SEMÂNTICA

Semântica de Linguagens de Programação

Tipos Algébricos. Programação Funcional. Capítulo 11. José Romildo Malaquias Departamento de Computação Universidade Federal de Ouro Preto

Paradigmas de Programação. Java First-Tier: Aplicações. Orientação a Objetos em Java (I) Nomenclatura. Paradigma OO. Nomenclatura

Conceitos de Linguagem de Programação - 2

Linguagens de Programação. Nomes, Escopos e Vinculações (Bindings) Carlos Bazilio

Expressões Condicionais

Pedro Vasconcelos DCC/FCUP. Programação Funcional 19 a Aula Raciocinar sobre programas

FACULDADE LEÃO SAMPAIO

Programação Funcional Aulas 9, 10 & 11

Algoritmos e Estruturas de Dados I 01/2013. Vetores e Recursividade. Pedro O.S. Vaz de Melo

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

Recursão. Aula 1. Liana Duenha. Faculdade de Computação Universidade Federal de Mato Grosso do Sul

Linguagens de Domínio Específico

2. Diga qual é a diferença entre tipos de informação elementares e tipos de informação estruturados.

Histórico. Origens da linguagem

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

INF 1005 Programação I

ÍNDICE. PREFÁCIO xv. 3 PROCESSOS GERADOS POR PROCEDIMENTOS Recursão Linear Cálculo de potências Cálculo de factoriais 91

SCALA! Mariah Barros Cardoso Ruann Magalhães Homem Rudá Martinez Pimentel Deeke Yuri Pereira Constante

Estruturas de Dados Pilhas, Filas, Listas

Linguagem Haskell. Riocemar S. de Santana

Universidade de Santa Cruz do Sul UNISC Departamento de informática COMPILADORES. Introdução. Geovane Griesang

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

UNIP - Ciência da Computação e Sistemas de Informação. Estrutura de Dados. AULA 5 Pilhas

Inteligência Artificial

Técnicas de análise de algoritmos

ALGORITMOS AVANÇADOS UNIDADE II Recursividade. Luiz Leão

Estruturas de Dados Pilhas, Filas, Listas

Algoritmos e Estruturas de Dados I

Introdução a Programação de Jogos

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

Linguagens de Programação Classificação

Computação II Orientação a Objetos

ACH2043 INTRODUÇÃO À TEORIA DA COMPUTAÇÃO

Transcrição:

PROGRAMAÇÃO FUNCIONAL NOTAS DE AULAS Prof. Luciano Silva 2014

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 01 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: FUNDAMENTOS DE CÁLCULO LAMBDA (I) Nossos objetivos nesta semana são: apresentar o conceito de expressão lambda e sua importância para a programação funcional construir programas funcionais utilizando expressões lambda utilizar a redução b para avaliar a aplicação de um programa funcional Para esta semana, usamos como referências as seções 2.3 a 2.9 do nosso livro da referência básica: MICHAELSON, G. Introduction to Functional Programming Through Lambda Calculus. Workingham: 1989. Não deixem de ler estas seções após esta aula! CÁLCULO LAMBDA O Cálculo Lambda ( ou l-cálculo) foi desenvolvido em 1930 pelo matemático Alonzo Church, como um modelo para computabilidade. Trata-se de uma linguagem formal muito simples, que pode ser utilizada para formalizar diversos aspectos de programação e linguagens de programação. Para o paradigma de Programação Funcional, o Cálculo Lambda por ser visto como um Código de Máquina para linguagens funcionais. 1

Essencialmente, o Cálculo Lambda manipula expressões lambda. Uma expressão lambda é definida pela seguinte gramática formal: O nome representa uma variável ou uma constante. Já uma função (ou abstração) é uma expressão da forma: A seguir, temos alguns exemplos de expressões como abstrações: Observem que l sempre precede um nome. Este nome é chamado de variável ligada (bound variable). Uma das grandes vantagens da programação é que podemos passar explicitamente uma função como uma variável ligada, conforme mostrado no último exemplo acima. Finalmente, uma aplicação permite associar um valor às variáveis ligadas de uma abstração. A sintaxe para aplicações é a seguinte: Uma aplicação também é conhecido como par ligado (bound pair). Abaixo, temos um exemplo de aplicação: Existem duas abordagens para se calcular aplicações: Redução por ordem aplicativa (chamada por valor): o parâmetro é calculado antes de ser passado como um parâmetro formal. Redução por ordem normal (chamada por nome): o parâmetro não é calculado antes de ser passado como um parâmetro formal. A ordem normal é mais poderosa que a ordem aplicativa, porém pode ser menos eficiente. Veremos isto quando estudarmos lazy evaluation. 2

EXERCÍCIO TUTORIADO Para cada uma das expressões lambda abaixo, classifique-a como uma abstração ou uma aplicação. Explique o que significa cada uma delas. 3

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Construa abstrações para cada uma das funções abaixo: uma função que receba duas funções f e g e produza a função composta fog. uma função que receba duas funções f e g, um argumento x e produza a aplicação fog(x). uma função que receba duas funções f e g e produza a função média destas duas funções, isto é, m=(f+g)/2. 4

NOMEAÇÃO DE ABSTRAÇÕES Para tornar mais simples a manipulação de abstrações, podemos associar nomes a elas com a seguinte sintaxe: Como exemplos, vamos nomear algumas abstrações colocadas no exercício anterior: Nomeações podem ser utilizadas em outras nomeações, como no exemplo abaixo: Nomeações são mapeadas naturalmente em algumas linguagens funcionais como Scheme. Por exemplo, vamos considerar novamente a nomeação identity: Esta nomeação poderia ser mapeada da seguinte forma na linguagem Scheme: (define identity (lambda (x) x ) ) Notação: no cálculo de uma aplicação, vamos utilizar o símbolo == para indicar a substituição de uma nomeação pela abstração associada. 5

REDUÇÃO BETA (b) A redução beta é um processo fundamental para avaliar o valor de uma aplicação. Esta redução é definida matematicamente por: Essencialmente, esta redução transforma uma aplicação em uma expressão, associando o argumento da aplicação à variável ligada da abstração. A expressão gerada é chamada de b-redex (redex=reductible expression.). A partir deste ponto, vamos indicar a redução b por: Abaixo, temos uma sequencia de reduções b para avaliação de uma aplicação: EXERCÍCIO TUTORIADO Avalie a aplicação abaixo utilizando a redução b: 6

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Considere a seguinte nomeação de abstração: Utilizando esta nomeação e redução b, avalie a aplicação abaixo: 7

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Considere a seguinte nomeação de abstração: Utilizando esta nomeação e redução b, avalie a aplicação abaixo: 8

EXERCÍCIOS EXTRA-CLASSE 1. Classifique as expressões lambda abaixo em abstrações e aplicações. Para cada uma delas, descreva o seu funcionamento. 2. Avalie cada uma das aplicações abaixo utilizando a redução b: 3. Para cada um dos pares de expressões abaixo, verifique se elas são equivalentes: 4. Considere a seguinte nomeação de abstração: Utilizando esta nomeação e redução b, avalie a aplicação abaixo: 9

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 02 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: FUNDAMENTOS DE CÁLCULO LAMBDA (II) Nossos objetivos nesta semana são: apresentar os conceitos de variáveis livres e ligadas conhecer o problema de conflito de nomes (name clash) e como resolvê-lo através de conversão α apresentar o mecanismo de redução h para simplificação de expressões l Para esta semana, usamos como referências as seções 2.10 a 2.12 do nosso livro da referência básica: MICHAELSON, G. Introduction to Functional Programming Through Lambda Calculus. Workingham: 1989. Não deixem de ler estas seções após esta aula! VARIÁVEIS LIVRES E LIGADAS Saber diferenciar entre variáveis livres e ligadas, é um procedimento fundamental para que a redução b possa ser corretamente aplicada. Uma variável x é chamada de ligada (bound variable) se sua ocorrência no corpo de uma abstração é precedida de um lx. Quando a variável não é precedida por um l, então ela é dita livre (free variable). Por exemplo, x é ligada na expressão lx.x, y é livre na expressão lx.xy e, na expressão (lx.x)( ly.yx), x é ligada no primeiro l e livre no segundo l. 1

No processo de redução b, as substituições sempre são efetuadas nas variáveis. Por exemplo, consideremos a expressão lambda abaixo: Nesta expressão, temos três variáveis ligadas: f, x e s. Assim, a sequencia de reduções b fica da seguinte forma: Porém, se considerarmos a expressão abaixo temos a variável f ocorrendo ligada em dois escopos diferentes. Neste caso, a substituição deve ocorrer somente no primeiro f ligado, ou seja: (ls.(s s) lf.f) Para evitar possíveis confusões com escopos, podemos renomear determinadas variáveis. Veremos isto logo após o próximo exercício tutoriado. EXERCÍCIO COM DISCUSSÃO EM DUPLAS Identifique as variáveis ligadas e livres nas expressões abaixo: 2

CONFLITOS DE NOMES e a CONVERSÃO α Para entender o problema de conflito (clash) de nomes, vamos considerar o seguinte exemplo: A variável arg aparece como ligada para o lambda mais interno e livre para o lambda mais externo. Assim, se aplicarmos a redução b, podemos ter o seguinte problema: Isto ocorre porque temos um conflito de nomes entre as duas instâncias de arg. Para evitar este conflito de nomes, podemos renomear a variável arg vinculada ao lambda mais interno para arg1: Esta renomeação é conhecida como conversão alfa (α). 3

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Verifique se as expressões abaixo podem ter conflito de nomes e, caso haja, mostre um exemplo onde a redução b falha e aplique a conversão α para resolvê-lo: 4

REDUÇÃO ETA (h) Considere uma expressão lambda da seguinte forma: Observe que o objetivo desta expressão é somente passar o argumento <name> para <expressão>. Aplicando a redução b sobre um argumento <argument> genérico, teremos: Com base nesta redução, observa-se facilmente que não há necessidade da abstração lambda externa, ou seja, ela é redundante e pode ser eliminada para simplificar a expressão. A redução que permite transformar l<name>.(<expression.> <name>) em somente <expression.> é chamada de redução eta (h). EXERCÍCIO COM DISCUSSÃO EM DUPLAS Reduza as abstrações lambda redundantes abaixo, utilizando a redução eta. lx.(y x) lx.((+ x x) x) 5

EXERCÍCIOS EXTRA-CLASSE 1. Analise cada uma das expressões lambda abaixo e identifique as variáveis livres e ligadas: 2. Para cada uma das expressões acima, identifique se há possibilidade de conflito de nomes e, em caso afirmativo, mostre como o conflito pode levar a uma aplicação equivocada da redução beta e utilize a conversão alpha para eliminar o conflito. 3. Para cada uma das expressões acima, já com a conversão alpha, verifique se ela pode ser simplificada com a redução eta. 6

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 03 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: MAPEAMENTO DO CÁLCULO LAMBDA PARA HASKELL e SCALA Nossos objetivos nesta aula são: apresentar os ambientes HUGS (Haskell) e Eclipse Scala. mapear abstrações e aplicações do cálculo lambda para Haskell e Scala Para esta semana, usamos como referências os Capítulos 1 e 2 do nosso livro da referência básica para os fundamentos de Haskell: THOMPSON, S. Haskell: the Craft of Functional Programming. 3.ed. New York: Addison-Wesley, 2011. Usamos, também, como referências os Capítulos 1 e 2 do nosso livro da referência básica para os fundamentos de Scala: ODERSKY, M. Programming in Scala.2.ed. New York: Artima, 2008. Não deixem de ler estes capítulos após esta aula! LINGUAGEM HASKELL Haskell é uma linguagem de programação puramente funcional, de propósito geral, nomeada em homenagem ao lógico Haskell Curry. Como toda linguagem funcional, a estrutura de controle primária é uma função. 1

Características do Haskell incluem o suporte a funções recursivas e tipos de dados, casamento de padrões, list comprehensions, guard statements e avaliação preguiçosa, esta, um elo em comum entre os diversos grupos de desenvolvimento da linguagem. A combinação destas características pode fazer com que a construção de funções que seriam complexas em uma linguagem procedimental de programação tornem-se uma tarefa quase trivial em Haskell. As seguintes implementações estão totalmente, ou quase, de acordo com o padrão Haskell 98. Todas são distribuídas sob licenças código aberto: o GHC. O Glasgow Haskell Compiler gera código nativo de diferentes arquitecturas e pode também gerar código C. Ele é provavelmente o mais popular compiladorhaskell, e algumas bibliotecas (como bindings para OpenGL) funcionam apenas com ele. o Hugs é um interpretador de bytecode. Oferece rápida compilação dos programas e razoável velocidade de execução. Também dispõe de uma simples biblioteca gráfica. Hugs é ideal para pessoas que estão aprendendo os básicos de Haskell. É a mais portável e leve das implementações de Haskell. o nhc9819 é outro compilador que gera bytecode. O bytecode resultante executa significativamente mais rápido do que o equivalente do Hugs. Nhc98 foca na minimização do uso de memória, e é uma boa escolha para máquinas velhas/lentas. o HBC é outro compilador Haskell para código nativo. Seu desenvolvimento não está ativo, mas ele é funcional. o Helium20 é um novo dialeto do Haskell. O foco é na facilidade de aprendizado. Atualmente, carece de typeclasses, tornando-o incompatível com muitos programas Haskell. EXERCÍCIO TUTORIADO Compilar e executar o programa Haskell abaixo no ambiente GHC: olamundo :: IO() olamundo = putstrln "Olá, Mundo!" main = olamundo Para compilar, fazemos: ghc XDataKinds o primeiro primeiro.hs Para executar:./primeiro Podemos também usar o ghci (ghc interativo) Para sair do ghci (CTRL-D): ghci Prelude>:load primeiro.hs *Main> main 2

EXERCÍCIO TUTORIADO Compilar a abstração abaixo em Haskell (GHC). Aplicar esta abstração no valor 5. Qual a expressão em cálculo lambda correspondente a este programa? fatorial :: Integer -> Integer fatorial 0 = 1 fatorial n n > 0 = n * fatorial (n-1) main = print (fatorial 5) EXERCÍCIO COM DISCUSSÃO EM DUPLAS Escrever uma abstração lambda para calcular o n-ésimo número de Fibonacci. Implementar esta abstração em Haskell (GHC). Aplique a abstração para calcular o 5-ésimo número de Fibonacci. EXERCÍCIO TUTORIADO Linguagens funcionais como Haskell permite que algoritmos relativamente complexos como, por exemplo, o Quicksort possam ser facilmente implementados com listas. Compile a abstração abaixo e a aplique na lista [3,4,5,6,7,0]. quicksort :: (Ord a) => [a] -> [a] quicksort [] = [] quicksort (s:xs) = quicksort [x x <- xs,x < s] ++ [s] ++ quicksort [x x <- xs,x >= s] 3

LINGUAGEM SCHEME Scala (Scalable language) é uma linguagem de programação de propósito geral, multiparadigma (paradigma OO e funcional). Scala é plenamente interoperável com Java e é a sucessora de Funnel, uma linguagem baseada em join calculus. Existem diversos ambientes para desenvolvimento em Scala. Na nossa disciplina, utilizaremos o ambiente integrado ao Eclipse: EXERCÍCIO TUTORIADO Compile e execute a aplicação Scala mostrada abaixo: object Exemplo { def main(args: Array[String]) { println("hello World"); } } 4

EXERCÍCIO TUTORIADO Compile e execute a aplicação Scala abaixo. Identifique a abstração e aplicação lambdas: object FactorialRecursion { def main(args: Array[String]) { println(factorial(5)) } } def fatorial(n: Int): Int = { if (n == 0) return 1 else return n * fatorial(n-1) } Uma outra forma de se implementar a função fatorial é: def fatorial(n: Int): Int = n match { case 0 => 1 case _ => n * fatorial(n-1) } EXERCÍCIO COM DISCUSSÃO EM DUPLAS Escrever uma abstração lambda para calcular o n-ésimo número de Fibonacci. Implementar esta abstração em Scala. Aplique a abstração para calcular o 5-ésimo número de Fibonacci. 5

EXERCÍCIOS EXTRA-CLASSE 1. Construa abstrações em cálculo lambda para: Calcular o maior de dois números Trocar o conteúdo de duas variáveis 2. A partir das abstrações acima, construa um exemplo de aplicação para cada uma delas e mostre, através da das reduções e conversões vistas, o resultado da aplicação. 3. Implemente as abstrações e aplicações em Haskell. 4. Implemente as abstrações e aplicações em Scala. 6

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 04 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: FUNÇÕES E RECURSÃO (PARTE I) Nossos objetivos nesta aula são: caracterizar a chamada recursiva de funções em expressões l desenvolver expressões l com recursão para diversos algoritmos recursivos clássicos Para esta aula, usamos como referências o Capítulo 4 (Recursão e Aritmética) da nossa referencia básica: MICHAELSON, G. Introduction to Functional Programming Through Lambda Calculus. Workingham: 1989. Não deixem de ler este capítulo depois da aula de hoje! FUNÇÕES RECURSIVAS Uma função recursiva é uma função que invoca a si própria para produzir um determinado resultado. Por exemplo, para calcular a soma de dois números inteiros x e y, podemos fazer a seguinte sequencia de chamadas recursivas: x+y = (x+1)+(y-1) = ((x+1)+1)+((y-1)-1) =... = (((x+1)+1)+1)+1... ou seja, para se obter a soma, podemos somar y vezes o número 1 ao x. 1

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Para calcular a soma recursivamente, considere a seguinte expressão l: def add1 f x y = if iszero y then x else f f (succ x) (pred y) def add = add1 add1 Mostre o resultado de add one two. 2

EXERCÍCIO TUTORIADO Explique qual é a utilidade da construção f f (succ x) (pred y) no programa anterior. 3

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Utilizando a inspiração do exercício da página 2, construa uma expressão lambda para calcular o produto de dois números naturais x e y: def mult1 f x y = def mult = mult1 mult1 4

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Mostre o resultado de mult one two. 5

EXERCÍCIOS EXTRA-CLASSE 1. Produza uma versão recursiva para calcular a potência x y : def power1 f x y =... def power = power1 power1 Mostre o resultado de power two three. 2. Produza uma versão recursiva para calcular a diferença x-y: def sub1 f x y =... def sub = sub1 sub1 Mostre o resultado de sub three two. 3. Produza uma versão recursiva para calcular o quociente da divisão inteira x/y: def div1 f x y =... def div = div1 div1 Mostre o resultado de div four two. 6

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 05 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: FUNÇÕES E RECURSÃO (PARTE II) Nossos objetivos nesta aula são: generalizar o processo de construção de funções recursivas via combinador Y aplicar o combinador Y para diversos problemas recursivos Para esta aula, usamos como referências o Capítulo 4 (Recursão e Aritmética) da nossa referencia básica: MICHAELSON, G. Introduction to Functional Programming Through Lambda Calculus. Workingham: 1989. Não deixem de ler este capítulo depois da aula de hoje! COMBINADOR Y Na nossa última aula, aprendemos uma estratégia para construir funções recursivas com expressões l, através da passagem de uma função como argumento dela mesma, conforme mostrado abaixo: def add1 f x y = if iszero y then x else f f (succ x) (pred y) def add = add1 add1 Porém, isto não é um processo muito natural para se obter tal tipo de função. 1

Veremos, agora, uma maneira padronizada de se produzir funções recursivas em expressões lambda partindo-se de versões recursivas iniciais e aplicando-se um produtor de funções recursivas chamado combinador Y. Vamos considerar, novamente, a função para calcular o produto de dois números naturais. Pode-se criar uma versão recursiva inicial da seguinte forma: PERGUNTA: Por que não podemos considerar esta versão da função como a versão definitiva? O primeiro passo é remover a auto-referência à função, da seguinte forma: Para transformar esta função (não-recursiva) em função recursiva, vamos utilizar um produtor de funções recursivas chamado combinador Y. Data uma função não-recursiva f, o combinador Y (recursive) é da seguinte forma: EXERCÍCIO TUTORIADO Explique o que faz o combinador Y. 2

Utilizando o combinador Y para a função multi1, teremos a versão recursiva da função de multiplicação fica como: EXERCÍCIO TUTORIADO Mostre como ficaria a função mult expandindo a aplicação recursive mult1: 3

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Calcule o resultado de multo one two, utilizando a versão recursiva de mult definida pelo combinador Y. 4

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Reprograme a função add, vista na aula passada, segundo a técnica do combinador Y estudada na aula de hoje. def add1 f x y = if iszero y then x else f f (succ x) (pred y) def add = add1 add1 Mostre o resultado de add one two. 5

EXERCÍCIOS EXTRA-CLASSE Reprograme as funções dos exercícios extra-classe da Aula 10 segundo a técnica com combinador Y aprendida da aula de hoje: 1. Produza uma versão recursiva para calcular a potência x y : def power1 f x y =... def power = recursive power1 Mostre o resultado de power two three. 2. Produza uma versão recursiva para calcular a diferença x-y: def sub1 f x y =... def sub = recursive sub1 Mostre o resultado de sub three two. 3. Produza uma versão recursiva para calcular o quociente da divisão inteira x/y: def div1 f x y =... def div = recursive div1 Mostre o resultado de div four two. 6

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 06 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: IMPLEMENTAÇÃO DE FUNÇÕES RECURSIVAS EM HASKELL Nossos objetivos nesta aula são: Recordar os princípios de construção de funções recursivas em Haskell Implementar as funções recursivas das aulas anteriores em Haskell Para esta semana, usamos como referências os Capítulos 1 e 2 do nosso livro da referência básica para os fundamentos de Haskell: THOMPSON, S. Haskell: the Craft of Functional Programming. 3.ed. New York: Addison-Wesley, 2011. Não deixem de ler estes capítulos após esta aula! BREVE REVISÃO DE HASKELL Compilar e executar o programa Haskell abaixo no ambiente GHC: olamundo :: IO() olamundo = putstrln "Olá, Mundo!" main = olamundo Para compilar, fazemos: ghc XDataKinds o primeiro primeiro.hs Para executar:./primeiro Podemos também usar o ghci (ghc interativo) Para sair do ghci (CTRL-D): ghci Prelude>:load primeiro.hs *Main> main 1

EXERCÍCIO TUTORIADO Compilar a abstração abaixo em Haskell (GHC). Aplicar esta abstração no valor 5. Qual a expressão em cálculo lambda correspondente a este programa? fatorial :: Integer -> Integer fatorial 0 = 1 fatorial n n > 0 = n * fatorial (n-1) main = print (fatorial 5) EXERCÍCIO COM DISCUSSÃO EM DUPLAS Implementar a função recursiva abaixo em Haskell: def add1 f x y = if iszero y then x else f f (succ x) (pred y) def add = add1 add1 Mostre o resultado de add one two. 2

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Complete e implemente em Haskell uma função recursiva para multiplicação de dois números naturais: def mult1 f x y = def mult = mult1 mult1 Mostre o resultado de mult para mult two three. 3

EXERCÍCIOS EXTRA-CLASSES 1. Produza uma versão recursiva para calcular a potência x y e a implemente em Haskell: def power1 f x y =... def power = power1 power1 Mostre o resultado de power two three. 2. Produza uma versão recursiva para calcular a diferença x-y e a implemente em Haskell: def sub1 f x y =... def sub = sub1 sub1 Mostre o resultado de sub three two. 3. Produza uma versão recursiva para calcular o quociente da divisão inteira x/y e a implemente em Haskell: def div1 f x y =... def div = div1 div1 Mostre o resultado de div four two. 4

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 07 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: IMPLEMENTAÇÃO DE FUNÇÕES RECURSIVAS EM SCALA Nossos objetivos nesta aula são: Recordar os princípios de construção de funções recursivas em Scala Implementar as funções recursivas das aulas anteriores em Scala Usamos, também, como referências os Capítulos 1 e 2 do nosso livro da referência básica para os fundamentos de Scala: ODERSKY, M. Programming in Scala.2.ed. New York: Artima, 2008. Não deixem de ler estes capítulos após esta aula! BREVE REVISÃO DE SCALA Scala (Scalable language) é uma linguagem de programação de propósito geral, multiparadigma (paradigma OO e funcional). Scala é plenamente interoperável com Java e é a sucessora de Funnel, uma linguagem baseada em join calculus. Existem diversos ambientes para desenvolvimento em Scala. Na nossa disciplina, utilizaremos o ambiente integrado ao Eclipse: 1

EXERCÍCIO TUTORIADO Compile e execute a aplicação Scala mostrada abaixo: object Exemplo { def main(args: Array[String]) { println("hello World"); } } EXERCÍCIO TUTORIADO Compile e execute a aplicação Scala abaixo. Identifique a abstração e aplicação lambdas: object FactorialRecursion { def main(args: Array[String]) { println(factorial(5)) } } def fatorial(n: Int): Int = { if (n == 0) return 1 else return n * fatorial(n-1) } Uma outra forma de se implementar a função fatorial é: def fatorial(n: Int): Int = n match { case 0 => 1 case _ => n * fatorial(n-1) } EXERCÍCIO COM DISCUSSÃO EM DUPLAS Implementar a função recursiva abaixo em Scala: def add1 f x y = if iszero y then x else f f (succ x) (pred y) def add = add1 add1 Mostre o resultado de add one two. 2

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Complete e implemente em Scala uma função recursiva para multiplicação de dois números naturais: def mult1 f x y = def mult = mult1 mult1 Mostre o resultado de mult para mult two three. 3

EXERCÍCIOS EXTRA-CLASSES 1. Produza uma versão recursiva para calcular a potência x y e a implemente em Scala: def power1 f x y =... def power = power1 power1 Mostre o resultado de power two three. 2. Produza uma versão recursiva para calcular a diferença x-y e a implemente em Scala: def sub1 f x y =... def sub = sub1 sub1 Mostre o resultado de sub three two. 3. Produza uma versão recursiva para calcular o quociente da divisão inteira x/y e a implemente em Scala: def div1 f x y =... def div = div1 div1 Mostre o resultado de div four two. 4

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 08 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: AVALIAÇÃO FUNCIONAL (I) Nossos objetivos nesta aula são: caracterizar a forma de avaliação normal praticar com a forma de avaliação normal Para esta aula, usamos como referências as Seções 8.1(Termination and Normal Form) e 8.2 (Normal order) da nossa referencia básica: MICHAELSON, G. Introduction to Functional Programming Through Lambda Calculus. Workingham: 1989. Não deixem de ler este capítulo depois da aula de hoje! AVALIAÇÃO NORMAL Existem, basicamente, três formas para se avaliar o valor de aplicação de uma função: o ordem normal o ordem aplicativa o avaliação preguiçosa (lazy evaluation) Estudaremos, nas próximas semanas, cada um destes tipos de avaliação, destacando as vantagens e desvantagens de cada uma delas. 1

Dizemos que uma expressão lambda está na forma normal se ela não puder ser mais reduzida. EXERCÍCIO COM DISCUSSÃO EM DUPLAS Considere as duas expressões lambda mostradas abaixo. Faça as reduções até o ponto em que não seja mais possível se realizar reduções. Dizemos que uma aplicação é um redex (reductible expression) se puder ser reduzida. Alternativamente, podemos dizer que uma expressão lambda está na forma normal se ela não contém nenhum redex. EXERCÍCIO COM DISCUSSÃO EM DUPLAS Identifique, nas expressões do exercício anteriores, aquelas que são redex e quais delas estão na forma normal. 2

Na avaliação normal, a redução! sempre irá operar no redex o mais à esquerda possível. EXERCÍCIO COM DISCUSSÃO EM DUPLAS Avalie a expressão abaixo utilizando a avaliação normal. Conte quantas vezes a aplicação (ADD 1 2) é avaliada. 3

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Avalie a expressão abaixo utilizando a avaliação normal. Conte quantas reduções foram efetuadas. 4

EXERCÍCIOS EXTRA-CLASSE Avalie as expressões abaixo utilizando a avaliação normal. Conte quantas reduções foram efetuadas. 5

6

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 09 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: AVALIAÇÃO FUNCIONAL (II) Nossos objetivos nesta aula são: caracterizar a forma de avaliação aplicativa praticar com a forma de avaliação aplicativa Para esta aula, usamos como referências a Seção 8.3(Applicative Order) da nossa referencia básica: MICHAELSON, G. Introduction to Functional Programming Through Lambda Calculus. Workingham: 1989. Não deixem de ler esta seção depois da aula de hoje! AVALIAÇÃO APLICATIVA Vimos, na aula passada, que a avaliação normal pode gerar várias reavaliações de partes de uma expressão. Por exemplo, na aplicação abaixo, reavaliamos (ADD 1 2) quatros vezes. 1

Assim, ao invés de fazermos as reduções o mais à esquerda possível, podemos fazer a redução no redex interno o mais à esquerda possível. EXERCÍCIO TUTORIADO Considere a aplicação ADD 1 (ADD 1 2), mostrada abaixo: (a) identifique o redex interno o mais à esquerda possível. (b) aplique a avaliação aplicativa e avalie a aplicação. 2

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Avalie a expressão abaixo utilizando a avaliação aplicativa. 3

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Avalie a expressão abaixo utilizando a avaliação normal e avaliação aplicativa. Compare a quantidade de reduções efetuadas. 4

5

EXERCÍCIOS EXTRA-CLASSE Avalie as expressões abaixo utilizando a avaliação normal e a avaliação aplicativa. Compare a quantidade de reduções efetuadas. 6

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 10 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: AVALIAÇÃO FUNCIONAL (III) Nossos objetivos nesta aula são: caracterizar a forma de avaliação adiada de aplicações para evitar recursões infinitas aprender a definir objetos infinitos em expressões lambda praticar com a forma de avaliação adiada Para esta aula, usamos como referências a Seção 8.4(Delaying Evaluation) e 8.6 (Infinite Objects) da nossa referencia básica: MICHAELSON, G. Introduction to Functional Programming Through Lambda Calculus. Workingham: 1989. Não deixem de ler esta seção depois da aula de hoje! AVALIAÇÃO ADIADA (DELAYED EVALUATION) Vimos, na aula passada, que a avaliação aplicativa pode gerar uma recursão infinita quando aplicada a, por exemplo, expressões como a mostrada abaixo: Quando um redex mais interno e mais à esquerda possível já possui, por exemplo, uma auto-recursão, o esquema de avaliação aplicativa pode gerar uma recursão infinita. Nestes casos, devemos adiar a avaliação e tomar o redex externo mais próximo. 1

EXERCÍCIO TUTORIADO Considere a aplicação mostrada abaixo: (a) localize o redex mais interno e mais à esquerda possível e verifique se ele não possui auto-recursão. (b) Caso afirmativo, adie esta avaliação e tente reduzir pelo redex externo mais próximo. 2

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Considere a aplicação mostrada abaixo: (c) localize o redex mais interno e mais à esquerda possível e verifique se ele não possui auto-recursão. (d) Caso afirmativo, adie esta avaliação e tente reduzir pelo redex externo mais próximo. Caso negativo, continue as reduções e verifique se é possível produzir um valor para a expressão. 3

OBJETOS INFINITOS A avaliação adiada, além de nos permitir tratar alguns problemas de recursão infinita na avaliação aplicativa, também nos permite construir objetos infinitos. Por exemplo, suponha que queiramos representar todos os números naturais em um programa. Numa linguagem imperativa ou OO, por exemplo, isto não seria possível pois já na declaração do conjunto dos números naturais, já teríamos um estouro de memória. Porém, em linguagens funcionais isto é bastante simples: Relembrando de Paradigmas de Linguagens, a função cons X Y irá adicionar o elemento X no início da lista Y. EXERCÍCIO TUTORIADO Faça a avaliação de head(numbers), utilizando a avaliação aplicativa com adiamento da avaliação, lembrando que head devolve o primeiro elemento de uma lista. 4

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Faça a avaliação de head(tail(numbers)), utilizando a avaliação aplicativa com adiamento da avaliação e lembrando que tail calcula a sublista de uma lista, resultado da remoção do primeiro elemento da lista. 5

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Construa uma expressão lambda pares para representar todos os números naturais pares. Proponha uma expressão lambda para calcular o segundo número par e resolva esta expressão utilizando a avaliação aplicativa com adiamento de avaliação. 6

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Construa uma expressão lambda fib para representar todos os números de Fibonacci. Proponha uma expressão lambda para calcular o segundo número de Fibonacci e resolva esta expressão utilizando a avaliação aplicativa com adiamento de avaliação. 7

EXERCÍCIOS EXTRA-CLASSE 1. Construa uma expressão lambda impares para representar todos os números naturais ímpares. Proponha uma expressão lambda para calcular o terceiro número ímpar e resolva esta expressão utilizando a avaliação aplicativa com adiamento de avaliação. 2. Construa uma expressão lambda multiplos n para representar todos os números naturais múltiplos de n. Proponha uma expressão lambda para calcular o quarto número múltiplo de n e resolva esta expressão utilizando a avaliação aplicativa com adiamento de avaliação. 8

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 11 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: AVALIAÇÃO FUNCIONAL (IV) Nossos objetivos nesta aula são: caracterizar a técnica de lazy evaluation (avaliação preguiçosa) praticar com lazy evaluation Para esta aula, usamos como referências a Seção 8.7 (Lazy Evaluation) da nossa referencia básica: MICHAELSON, G. Introduction to Functional Programming Through Lambda Calculus. Workingham: 1989. Não deixem de ler esta seção depois da aula de hoje! LAZY EVALUATION Lazy evaluation é um método de avaliação adiada, que evita múltiplas avaliações de uma mesma expressão. Lazy Evaluation combina as vantagens da avaliação normal e da avaliação aplicativa. Para que o esquema de Lazy Evaluation funcione, numeramos cada par limitado (bound pair) com um identificador único. Pares idênticos recebem o mesmo identificador. Durante a avaliação da expressão, quando um par limitado substitui uma variável, ele mantém o seu identificador. E, os pares limitados externos (e suas cópias), recebem novos identificadores. 1

Vamos considerar o seguinte exemplo, onde os pares limitados já estão identificados com números: Aplicando a ordem de avaliação normal, vamos avaliar a expressão identificada por 1. A substituição da variável s provoca a seguinte reenumeração: Vamos avaliar a expressão identificada por 2: Fazendo a substituição deste resultado na expressão anterior, obtemos a seguinte expressão com a sua nova reenumeração: que, avaliada, produz o resultado. Observem que a expressão foi avaliada uma única vez, repetindo economias semelhantes à avaliação aplicativa. EXERCÍCIO COM DISCUSSÃO EM DUPLAS Considere a abstração e aplicação mostradas abaixo: ADD 2 2 Usando a técnica de lazy evaluation, mostre passo-a-passo a avaliação da aplicação ADD 2 2. 2

3

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Considere a abstração e aplicação mostradas abaixo: ADD 3 4 Usando a técnica de lazy evaluation, mostre passo-a-passo a avaliação da aplicação ADD 3 4. 4

EXERCÍCIOS EXTRA-CLASSE Avalie as três expressões abaixo (se possível) com as técnicas de avaliação normal, avaliação aplicativa e lazy evaluation. Compare a quantidade de substituições de cada uma delas. 5

6

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 12 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: IMPLEMENTAÇÃO DE FUNÇÕES RECURSIVAS EM HASKELL Nossos objetivos nesta aula são: Recordar os princípios de construção de funções recursivas em Haskell Implementar as funções recursivas das aulas anteriores em Haskell Para esta semana, usamos como referências os Capítulos 1 e 2 do nosso livro da referência básica para os fundamentos de Haskell: THOMPSON, S. Haskell: the Craft of Functional Programming. 3.ed. New York: Addison-Wesley, 2011. Não deixem de ler estes capítulos após esta aula! BREVE REVISÃO DE HASKELL Compilar e executar o programa Haskell abaixo no ambiente GHC: olamundo :: IO() olamundo = putstrln "Olá, Mundo!" main = olamundo Para compilar, fazemos: ghc XDataKinds o primeiro primeiro.hs Para executar:./primeiro Podemos também usar o ghci (ghc interativo) Para sair do ghci (CTRL-D): ghci Prelude>:load primeiro.hs *Main> main 1

EXERCÍCIO TUTORIADO Compilar a abstração abaixo em Haskell (GHC). Aplicar esta abstração no valor 5. Qual a expressão em cálculo lambda correspondente a este programa? fatorial :: Integer -> Integer fatorial 0 = 1 fatorial n n > 0 = n * fatorial (n-1) main = print (fatorial 5) EXERCÍCIO COM DISCUSSÃO EM DUPLAS Implementar a função recursiva abaixo em Haskell: def add1 f x y = if iszero y then x else f f (succ x) (pred y) def add = add1 add1 Mostre o resultado de add one two. 2

EXERCÍCIO COM DISCUSSÃO EM DUPLAS Complete e implemente em Haskell uma função recursiva para multiplicação de dois números naturais: def mult1 f x y = def mult = mult1 mult1 Mostre o resultado de mult para mult two three. 3

EXERCÍCIOS EXTRA-CLASSES 1. Produza uma versão recursiva para calcular a potência x y e a implemente em Haskell: def power1 f x y =... def power = power1 power1 Mostre o resultado de power two three. 2. Produza uma versão recursiva para calcular a diferença x-y e a implemente em Haskell: def sub1 f x y =... def sub = sub1 sub1 Mostre o resultado de sub three two. 3. Produza uma versão recursiva para calcular o quociente da divisão inteira x/y e a implemente em Haskell: def div1 f x y =... def div = div1 div1 Mostre o resultado de div four two. 4

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 13 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: TIPOS ALGÉBRICOS (PARTE II) Nossos objetivos nesta aula são: revisar os conceitos básicos de tipos algébricos praticar com tipos algébricos em Haskell Para esta semana, usamos como referências o Capítulo 14 (Algebraic Types) do nosso livro da referência básica para os fundamentos de Haskell: THOMPSON, S. Haskell: the Craft of Functional Programming. 3.ed. New York: Addison-Wesley, 2011. Não deixem de ler este capítulo depois da aula de hoje! TIPOS ALGÉBRICOS EM HASKELL Aprendemos, na nossa última aula, que um tipo de dado algébrico (TDA) ou, simplesmente, tipo algébrico é definido indutivamente por: o 1 (elemento identidade) e 0 (elemento neutro) são tipos algébricos o todo tipo primitivo T é um tipo algébrico o se! " #! % são tipos algébricos, então também serão tipos algébricos:! "! % (produto de dois tipos algébricos)! " +! % (soma de dois tipos algébricos) Um exemplo típico de TDA é uma lista de números inteiros L, definida por: L = nil + Int L onde nil representa a lista vazia, Int o tipo primitivo para representar números inteiros, + a operação de união de tipos como conjuntos e a inclusão de um elemento no início da lista L. 1

Nosso objetivo, agora, é mapear as construções da nossa última aula na linguagem Haskell. EXERCÍCIO TUTORIADO Implemente o tipo algébrico de lista de números inteiros em Haskell. EXERCÍCIOS COM DISCUSSÃO EM DUPLAS (a) Especifique algebricamente o tipo NAT, para representar os números naturais. (b) Implemente o tipo NAT na linguagem Haskell. 2

EXERCÍCIOS COM DISCUSSÃO EM DUPLAS (a) Especifique algebricamente o tipo INTSTACK, para representar pilhas de números inteiros. (b) Implemente o tipo INTSTACK na linguagem Haskell. (c) Especifique algebricamente o tipo GENERICSTACK, para representar pilhas genéricas de tipos primitivos. (d) Implemente o tipo GENERICCSTACK na linguagem Haskell. 3

(e) Especifique algebricamente o tipo TREE, para representar árvores binárias genéricas de tipos primitivos. (f) Implemente o tipo GENERICCSTACK na linguagem Haskell. 4

EXERCÍCIOS EXTRA-CLASSE 1. Construa um tipo algébrico para o tipo de dado booleano. Sugestão: um tipo de dado algébrico pode ser definido utilizando mais de um tipo de produto. Utilize as operações booleanas conhecidas para definir os produtos. Implemente este tipo em Haskell. 2. Construa um tipo algébrico para o tipo de dado INTQUEUE, para representar filas de números inteiros. Deixe bem claras as semânticas da operação de soma e de produto. Implemente este tipo em Haskell. 3. Construa um tipo algébrico para o tipo de dado QUEUE, para representar filas de tipos primitivos genéricos. Deixe bem claras as semânticas da operação de soma e de produto. Implemente este tipo em Haskell. 4. Construa um tipo algébrico para o tipo de dado NARYTREE, para representar árvores n- árias genéricas de tipos primitivos. Deixe bem claras as semânticas da operação de soma e de produto. Implemente este tipo em Haskell. 5

6

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 14 2º SEMESTRE/2014 Prof. Luciano Silva TEORIA: TIPOS ALGÉBRICOS (PARTE III) Nossos objetivos nesta aula são: Entender a diferença entre tipos algébricos abstratos e concretos em Haskell Implementar tipos algébricos concretos em Haskell a partir da definição data Para esta semana, usamos como referências o Capítulo 14 (Algebraic Types) do nosso livro da referência básica para os fundamentos de Haskell: THOMPSON, S. Haskell: the Craft of Functional Programming. 3.ed. New York: Addison-Wesley, 2011. Não deixem de ler este capítulo depois da aula de hoje! IMPLEMENTAÇÃO DE TIPOS ALGÉBRICOS EM HASKELL Aprendemos, na nossa última aula, que tipos algébricos são declarados em Haskell através da palavra reservada data. Em várias declarações que fizemos nesta aula, especificamos somente o comportamento do tipo, sem disponibilizar efetivamente a implementação deste tipo. Tipos algébricos em que somente especificamos o comportamento são chamados de tipos abstratos de dado. A implementação efetiva de um tipo abstrato de dados é chamado tipo concreto de dado, ou comumente, estrutura de dado. Vamos considerar, agora, uma versão mais completa de uma pilha genérica. A especificação desta pilha como tipo abstrato é mostrada abaixo: module Stack (Stack, empty, isempty, push, top, pop) where empty :: Stack t isempty :: Stack t -> Bool push :: t -> Stack t -> Stack t top :: Stack t -> t pop :: Stack t -> (a,stack t) 1

Esta definição abstrai todas as operações usuais de uma pilha e as exporta no formato de um módulo. Assim, poderemos posteriormente importar este módulo dentro dos nossos programas. A partir deste tipo abstrato, vamos disponibilizar uma implementação concreta através de listas em Haskell: module Stack (Stack, empty, isempty, push, top, pop) where empty :: Stack t isempty :: Stack t -> Bool push :: t -> Stack t -> Stack t top :: Stack a -> t pop :: Stack t -> (a,stack t) newtype Stack a = StackImpl [t] -- aqui, inicia-se a implementação empty = StackImpl [ ] isempty (StackImpl s) = null s push x (StackImpl s) = StackImpl (x:s) top (StackImpl s) = head s pop (StackImpl (s:ss)) = (s,stackimpl ss) EXERCÍCIO TUTORIADO A partir do código anterior, construa uma pilha de números inteiros com a seguinte sequencia de empilhamentos: 20 10 5 4 3. Depois: (a) mostre o elemento do topo (b) desempilhe os dois últimos elementos inseridos e mostre o valor do topo (c) mostre se a pilha está vazia ou não 2

EXERCÍCIO COM DISCUSSÃO EM DUPLAS (a) Especifique uma fila genérica em Haskell como um tipo abstrato de dado, contendo as operações de: criação de fila vazia, verificação se a fila está vazia ou não, inserção, remoção do primeiro elemento e consulta do primeiro elemento (sem remover). (b) Implemente uma versão concreta do tipo abstrato acima através de listas em Haskell. (c) A partir do código anterior, construa uma fila de números inteiros com a seguinte sequencia de inserção: 20 10 5 4 3. Depois: (a) mostre o primeiro elemento inserido (b) remova os dois primeiros elementos inseridos e mostre o primeiro elemento que restou na fila (c) mostre se a fila está vazia ou não 3

EXERCÍCIO COM DISCUSSÃO EM DUPLAS (a) Especifique uma árvore binária genérica em Haskell como um tipo abstrato de dado, contendo as operações de: criação de árvore vazia; construção de uma nova árvore recebendo o elemento que deverá ficar na raiz, a subárvore da esquerda e a subárvore da direita e consulta se um determinado elemento está na árvore. (b) Implemente uma versão concreta do tipo abstrato acima através de listas em Haskell. (c) A partir do código anterior, construa uma árvore com a estrutura mostrada abaixo e verifique se o elemento 10 está na árvore: 4

EXERCÍCIOS EXTRA-CLASSE 1. Modifique a implementação do tipo árvore do último exercício para que ela seja uma árvore binária de busca. Acrescente os métodos de inserção e remoção. 2. Um mapa é uma estrutura de dados em que os dados são acompanhados de um chave. Por exemplo, (TIA,nome aluno) é uma informação de um aluno indexada pelo campo TIA. Construa um mapa genérico em Haskell (tipo abstrato e concreto) que permita: a. Criação de um mapa vazio b. Inserção de uma um dado genérico com uma chave genérica c. Busca de um dado com uma chave genérica d. Remoção de um dado com uma chave genérica Para a implementação concreta, você pode utilizar uma lista ou uma árvore binária de busca. 5

6

FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional Aula 15 2º SEMESTRE/2014 Prof. Luciano Silva MINI-PROJETO: PROCESSAMENTO DE INFORMAÇÕES DO TWITTER Nossos objetivos nesta aula são: Aplicar a linguagem funcional Scala para acesso e processamento de posts do Twitter Especificar o mini-projeto da disciplina Usamos, também, como referências os Capítulos 1 e 2 do nosso livro da referência básica para os fundamentos de Scala: ODERSKY, M. Programming in Scala.2.ed. New York: Artima, 2008. Não deixem de ler estes capítulos após esta aula! FUNDAMENTOS DE ACESSO AO TWITTER COM SCALA Cada aplicação que acessa o Twitter deverá obter quatro chaves importantes: o Consumer Key (API Key) o Consumer Secret (API Secret) o Access Token o Acess Token Secret Além disto, devemos configurar se a aplicação será apenas de leitura ou de leitura/escrita. A obtenção das chaves, bem como a configuração de cada aplicação, é feita no endereço mostrado abaixo: apps.twitter.com 1

Para a programação de acesso, vamos utilizar o framework twitter4j, disponível em: http://twitter4j.org/en/ EXEMPLO 1: FAZER UM POST NO TWITTER import twitter4j.twitterfactory import twitter4j.auth.accesstoken object Exemplo extends App { } val twitter = new TwitterFactory().getInstance() twitter.setoauthconsumer("api Key", "API Secret") twitter.setoauthaccesstoken(new AccessToken("AcessToken","Acess Token Secret")); twitter.updatestatus("hello World!") EXEMPLO 2: OBTER A TIMELINE DO PROPRIETÁRIO DA APLICAÇÃO import twitter4j.twitterfactory import twitter4j.auth.accesstoken object Exemplo extends App { } val twitter = new TwitterFactory().getInstance() twitter.setoauthconsumer("api Key", "API Secret") twitter.setoauthaccesstoken(new AccessToken("AcessToken","Acess Token Secret")); val statuses = twitter.gethometimeline println(statuses) 2

EXEMPLO 3: REALIZAR UMA CONSULTA SOBRE UM DETERMINADO TERMO NO TWITTER import twitter4j.twitterfactory import twitter4j.auth.accesstoken import twitter4j.query object Exemplo extends App { val twitter = new TwitterFactory().getInstance() twitter.setoauthconsumer("api Key", "API Secret") twitter.setoauthaccesstoken(new AccessToken("AcessToken","Acess Token Secret")); } val query = new Query("Mackenzie"); val result = twitter.search(query) println("tweetes Found :" + result.gettweets.size) println(result) 3

MINI-PROJETO DATA DE ENTREGA: 18/11/2014 (INDIVIDUAL ou DUPLAS) Construa uma programa em Scala que consulte o seu último post e verifique, no Twitter, quais pessoas estão comentando sobre as mesmas hashtags que você. Como resultado, você deve produzir um novo post contendo o seguinte formato: As pessoas abaixo estão comentando a minha hashtag: #nomehashtag Nome da Pessoa1 - Texto do Comentário Nome da Pessoa2 - Texto do Comentário... Nome da PessoaN - Texto do Comentário Você (ou sua dupla) deve(m) entregar o código-fonte da aplicação (contendo todas as chaves de acesso) em Scala. 4