Informações
• Linguagens de Programação 2
Programação Funcional
Sérgio Soares
[email protected]
– Paradigma de Programação Funcional
•
•
•
•
Carga Horária: 60h
Horário: 2as e 6as das 10h30 as 12h10
Local: 2as no LIP4 e 6as no LIP1
Grupo
– http://groups.yahoo.com/group/lp2_poli
O que é Programação Funcional?
• Programação com alto nível de abstração
• Soluções elegantes, concisas e poderosas
• Funções: computam um resultado que
depende apenas dos valores das entradas
• Forte fundamentação teórica, o que permite
mais facilmente provas de propriedades
sobre os programas
Conceitos importantes
•
•
•
•
•
Sistema de tipos fortes
Uso extensivo de recursão
Polimorfismo e funções de alta ordem
Tipos de dados algébricos
Coleta de lixo (Garbage Collection)
Por que um curso de
programação funcional?
• Dá uma visão clara de conceitos
fundamentais da computação moderna:
– abstração (em uma função)
– abstração de dados (tipos abstratos de dados)
– genericidade, polimorfismo, overloading
Objetivos da programação
funcional
• Programação com um alto nível de
abstração, possibilitando:
– alta produtividade
– programas mais concisos
– programas mais fáceis de entender
– menos erros
– provas de propriedades sobre programas
Uso prático
• Programas com milhares de linhas de código:
compiladores, provadores de teoremas etc.
• Ericsson utiliza Erlang, uma linguagem
funcional concorrente, para programação de
switches de redes/telecomunicações, com
excelentes resultados.
• Possibilidade de integração com partes de
programas escritos em outras linguagens.
O curso
• A ênfase do curso é em conceitos
• Uso de Haskell
– Haskell é um ferramenta prática de apoio, mas
não o objetivo central
Ambiente a ser utilizado no curso
• Linguagem de programação: Haskell
• Interpretador Hugs: disponível para Windows
e Unix, gratuito
• Compilador GHC também está disponível
gratuitamente para Windows e Unix
Bibliografia
• Livro adotado:
– Haskell – The Craft of Functional Programming.
Simon Thompson. Addison-Wesley, 1996.
– http://www.uck.ac.uk/computer_science/Haskell_craft/
• Referências auxiliares
– Introduction to functional programming. R. Bird
and P. Wadler. Prentice Hall, 1988.
– http://www.lpac.ac.uk/SEL-HPC/Articles/FuncArchive.html
– http://www.haskell.org
Avaliação
• 2 exames escritos cobrindo o conteúdo da matéria
Histórico
Máquina
de Turing
Linguagens de
programação
imperativa
Lambda
Cálculo
Linguagens de
programação
funcional
• ??????? Seminário ??????????
• Trabalho de Implementação
• Exame final com toda a matéria
Histórico
• Anos 70
– Linguagens funcionais foram vistas como uma
forma de transpor a "crise de software", onde
grandes projetos de software falhavam porque
as ferramentas de programação eram
impróprias para estes objetivos específicos.
– “Can Programming Be Liberated From the
Von Neumann Style ? A Functional Style and
Its Algebra of Programs”, John Backus, 1978
CACM Turing Award Lecture
Programação Funcional
• Leva essa idéia ao extremo
– Sua sintaxe encoraja uma visão totalmente
modular do fluxo do programa
– Reutilização do código previamente escrito
(funções) para construir programas cada vez mais
complexos
– Geralmente não há um identificador (por exemplo
a função main( ) de C e Java) para indicar o ponto
onde a execução do programa inicia
Programação Funcional
• Todos os subprogramas são vistos como
funções
– Eles recebem argumentos e retornam soluções
simples.
– Relação explícita e precisa entre E/S
– A solução retornada é baseada inteiramente na
entrada
– O tempo em que uma função é chamada é
irrelevante
Programação Funcional
• Baseia-se na idéia de calcular
– Define-se as funções a serem usadas e o
processador para a linguagem calculará o valor
das expressões que usam estas funções
– Um programa funcional (ou script em Haskell)
consiste de um conjunto de definições de
funções/valores e uma expressão a ser
processada
Modelo Computacional
Mapeamento (função) de valores de entrada em valores
de saída
Entrada
Programa
Saída
Ausência de estado e comandos (atribuição + controle)
Relação clara e explícita entre entrada e saída
Características Gerais
• Estilo declarativo
– Não há o conceito de estado nem comandos
como atribuição
• Composição e decomposição suportados
Modularidade
• Programas manipulados como uma
expressão matemática
Prova e transformação de programas
Programação Funcional
Programação Funcional
Visão Crítica
Visão Crítica
• Vantagens
– Manipulação mais simples de programas
• Legibilidade
• Modularidade
– Prova de propriedades
• Problemas
– “O mundo não é funcional!”
– Implementações ineficientes
– Mecanismos primitivos de E/S e formatação
• Interface
addD a b = 2 * (a + b) = 2 * (b + a) = addD b a
– Semântica
– Transformação
– Concorrência explorada de forma natural
Notação: Programação baseada
em definições
Definição de Funções
answer :: Int
answer = 42
square :: Int -> Int
square x = x * x
greater :: Bool
greater = (answer > 71)
allEqual :: Int -> Int -> Int -> Bool
allEqual n m p = (n == m) && (m == p)
yes :: Bool
yes = True
Avaliando Expressões
• Encontrar o valor de uma expressão
• Usar definições das funções
addD :: Int -> Int -> Int
addD a b = 2 * (a+b)
addD 2 (addD 3 4)
= 2 * (2 + (addD 3 4))
= 2 * (2 + 2 * (3 + 4))
= 32
maxi :: Int -> Int -> Int
maxi n m | n >= m
= n
| otherwise = m
Prova de propriedades
• Exemplo:
addD a b = 2 * (a+b)
= 2 * (b+a) = addD b a
• Válida para quaisquer argumentos a e b
• Não seria válida em linguagens imperativas,
com variáveis globais.
Em uma linguagem imperativa...
Em um sistema de controle de vendas:
• suponha vendas semanais dadas pela função
int b = 1;
...
int f (int x) {
b = x;
return (5)
}
vendas :: Int -> Int
• total de vendas da semana 0 à semana n?
vendas 0 + vendas 1 + ... + vendas (n-1) + vendas n
totalVendas :: Int -> Int
totalVendas n
| n == 0
= vendas 0
| otherwise = totalVendas (n-1) + vendas n
addD (f 3) b == addD b (f 3) ?
Recursão
• Definir caso base, i.e. valor para fun
• Definir o valor para
fun
usando o valor de
fun
Este é o caso recursivo.
Casamento de Padrões
0
n
(n-1)
maxVendas :: Int -> Int
maxVendas n
| n == 0
= vendas 0
| otherwise = maxi (maxVendas (n-1))
(vendas n)
Casamento de Padrões
myNot :: Bool -> Bool
myNot True = False
myNot False = True
myOr :: Bool -> Bool -> Bool
myOr True x = True
myOr False x = x
myAnd :: Bool -> Bool -> Bool
myAnd False x = False
myAnd True x = x
Exemplo
• Permite usar padrões no lugar de variáveis, na
definição de funções:
maxVendas :: Int -> Int
maxVendas 0 = vendas 0
maxVendas n = maxi (maxVendas (n-1))
(vendas n)
totalVendas :: Int -> Int
totalVendas 0 = vendas 0
totalVendas n = totalVendas (n-1) +
vendas n
Regras para Padrões
• Todos os padrões (esquerda) devem ter
tipos compatíveis
• Os casos devem ser exaustivos
– não é obrigatório Î funções parciais
• Não deve haver ambiguidade
– Ordem dos padrões usada para resolver
conflitos
Notação
•
•
•
•
Notação
•f n + 1
• f (n + 1)
Maiúsculas: Tipos e Construtores
Minúsculas: funções e argumentos
case sensitive
comentários:
--isso é um comentario de uma linha
{- comentario de varias linhas... -}
•2 + 3
• (+) 3 2
• maxi 2 4
• 2 ‘maxi‘ 4
Exercícios
Erros comuns
square x =
*x
• Defina as seguintes funções:
x
answer = 42; newline = ’\n’
--OK
– fatorial fat :: Int -> Int
– compara se quatro números são iguais
all4Equal :: Int -> Int -> Int -> Int -> Bool
funny x = x +
1
Error! Unexpected ’;’
usando allEqual
– retorna quantos parâmetros são iguais
– all4Equal
howManyEqual :: Int -> Int -> Int -> Int
Funny x = x+1
Error! Undefined constructor ’Funny’
Definições Locais
sumSquares :: Int -> Int -> Int
sumSquares x y = sqX + sqY
where sqX = x * x
sqY = y * y
Definições Locais
maxThreeOccurs :: Int -> Int -> Int -> (Int,Int)
maxThreeOccurs m n p = (mx, eqCount)
where mx = maxiThree m n p
eqCount = equalCount mx m n p
...
sumSquares x y = sq x + sq y
where sq z = z * z
sumSquares x y = let sqX = x * x
sqY = y * y
in sqX + sqY
• let definições in expressão
• definições where definições
Exercícios
• Defina uma função que dado um valor
inteiro s e um número de semanas n,
retorna quantas semanas de 0 a n tiveram
venda igual a s.
Considerações Gerais
• Operações e variáveis
– Em linguagens imperativas, as operações são
executadas e os resultados armazenados em
variáveis para uso posterior
– O gerenciamento de variáveis é uma
preocupação constante e uma fonte de
complexidade para linguagens imperativas
Considerações Gerais
• Transparência Referencial
– Uma expressão pode ser sempre substituída
pelo seu valor (ou por outra expressão que
denote o mesmo valor)
• Composicionalidade
– Valor obtido a partir dos valores dos subcomponentes
Considerações Gerais
• Uma expressão sempre denota um único
valor
• Expressões podem conter variáveis
– variáveis não mudam de valor!
– Não há efeito colateral de qualquer espécie
Considerações Gerais
• Operações e variáveis
– Variáveis não são necessárias em linguagens
fucionais, como é o caso da matemática
– Em linguagens funcionais, a avaliação de uma
função sempre produz o mesmo resultado
quando fornecidos os mesmos parâmetros
• Transparência referencial
Download

Programação Funcional Informações O que é Programação