Programação Funcional

Propaganda
Programação Funcional
Lucília Camarão de Figueiredo
Universidade Federal de Ouro Preto
[email protected]
Aula 04: Definição de funções
1
D EFINIÇÃO
DE FUNÇÕES
f x1 x2 ...xn = E
Define uma função f de tipo T1 → T2 → ...→ Tn → T, onde
Ti é o tipo do i-ésimo argumento de f, para i=1,. . . .n, e T é o tipo
da expressão E (ou seja, o tipo do valor retornado por f)
Exemplos de operações:
double :: Num a => a → a
double x = 2*x
exOr :: Bool → Bool → Bool
exOr x y = (x || y) && (not (x && y))
max3 x y z :: Ord a => a → a → a → a
max3 x y z = max(max(x,y),z)
D EFINIÇÃO
DE FUNÇÕES
2
E XPRESSÕES C ONDICIONAIS
f x1 x2 ...xn = E
Na maioria das linguagens de programação, funções podem ser
definidas usando-se expressões condicionais:
max :: Ord a => a → a → a
max x y = if (x >= y) then x else y
abs :: Num a, Ord a => a → a
abs x = if x > 0 then x else -x
E XPRESSÕES C ONDICIONAIS
3
E XPRESSÕES C ONDICIONAIS
Expressões condicionais podem ser aninhadas:
signum x = if x>0 then 1 else
if x==0 then 0 else -1
Nota: Em Haskell, expressões condicionais devem sempre ter a
cláusula else — isso evita possíveis problemas de ambiguidade
envolvendo expressões condicionais aninhadas.
E XPRESSÕES C ONDICIONAIS
4
E QUAÇÕES
COM
G UARDAS
Como alternativa ao uso de expressões condicionais, podemos
definir funções usando equações com guardas:
abs x
| x > 0
= x
| otherwise = -x
signum x
| x>0 = 1
| x==0 = 0
| x<0 = -1
Equações com guardas tornam as definições mais legíveis.
Nota: A condição otherwise usada em equações com guardas é
definida no Prelude como otherwise = True.
E QUAÇÕES
COM
G UARDAS
5
C ASAMENTO
DE
PADRÃO
O uso casamento de padrão favorece a legibilidade:
not :: Bool → Bool
not True = False
not False = True
(&&) ::
True &&
True &&
False &&
False &&
C ASAMENTO
DE
PADRÃO
Bool →
True =
False =
True =
False =
Bool → Bool
True
False
False
False
6
C ASAMENTO
DE
PADRÃO
O operador && pode ser definido mais facilmente como:
True && True = True
_
&& _
= False
Entretanto, a seguinte definição é sempre mais eficiente (uma vez
que sempre evita a avaliação do segundo argumento):
False && _
True && b
= False
= b
Nota: O padrão _ corresponde a um "coringa", que casa com
qualquer argumento.
C ASAMENTO
DE
PADRÃO
7
PADRÕES
PARA
L ISTAS
Em Haskell, toda lista não vazia é construída por meo do operador
: (denominado cons), que adiciona um novo elemento ao início da
lista, ou seja, : tem tipo a → [a] → [a]:
[1,2,3]
significa
1:(2:(3:[]))
O operador cons também pode ser usado em padrões, caso no
qual ele destrói uma lista não vazia:
head :: a → [a]
head (x:_) = x
tail :: [a] → [a]
tail (_:xs) = xs
PADRÕES
PARA
L ISTAS
8
PADRÕES
PARA
L ISTAS
Mais alguns exemplos de definições de funções sobre listas:
length :: [a] → Int
length []
= 0
length (_:xs) = 1 + length xs
sum :: [a] → Int
sum []
= 0
sum (x:xs) = x + length xs
(++) :: [a] → [a] → [a]
[]
++ ys = ys
(x:xs) ++ ys = x:(xs++ys)
PADRÕES
PARA
L ISTAS
9
PADRÕES –
MAIS UM EXEMPLO :
A função a seguir determina a média de uma lista de valores
inteiros:
average :: [Int] → Float
average xs@(y:yx) = fromInt (sum xs) / fromInt (length xs)
Essa definição ilustra o uso de alias em um padrão.
A definição acima não é, entretanto, eficiente. Porque?
Uma definição eficiente será apresentada mais adiante.
PADRÕES –
MAIS UM EXEMPLO :
10
E XPRESSÕES L AMBDA
Podemos construir uma função sem que seja necessário dar um
nome a essa função — para isso, usamos uma lambda abstração:
λx → x+1
representa a função que, dado um argumento x, retorna x+1.
E XPRESSÕES L AMBDA
11
P ORQUE E XPRESSÕES L AMBDA
SÃO ÚTEIS ?
• Expressões Lambda podem ser usadas para dar significado
formal a definições de funções currificadas. Por exemplo:
add x y = x+y
significa
add = λx → (λx → x+y)
• Expressões Lambda são úteis para definir funções que
retornam funções como resultado. Por exemplo:
compose f g x = f (g x)
é mais naturalmente definida como:
compose f g = λx → f (g x)
P ORQUE E XPRESSÕES L AMBDA
SÃO ÚTEIS ?
12
E XERCÍCIOS
1. Dê 2 possíveis definições para o operador || usando
casamento de padrão.
2. Considere uma função safeTail, que se comporta como a
função tail, exceto que safeTail mapea a lista vazia em lista
vazia, enquanto tail produz um erro nesse caso. Defina
safeTail usando:
(a) uma expressão condicional
(b) equações com guardas
(c) casamento de padrão
Obs: A função null :: [a] → Bool, definida no Prelude,
pode ser usada para testar se uma lista é vazia. Como vocx̂e
definiria essa função?
E XERCÍCIOS
13
Download