Você está na página 1de 16

Programação Funcional

Aula 8

Funções Recursivas
Introdução

• Como já vimos anteriormente, muitas funções podem ser definidas


utilizando outras funções já anteriormente definidas.

• Exemplo:

factorial :: Int -> Int


factorial n = product [1..n]
Introdução
• O seguinte cálculo mostra como o fatorial pode ser calculado usando a
seguinte definição:
• Exemplo:
factorial 4
=
product [1..4]
=
product [1,2,3,4]
=
1*2*3*4
=
24
Funções Recursivas

• Em Haskell, também é permitido definir funções em termos de si


mesmos, caso em que as funções são chamadas recursiva.

• Recursividade é o mecanismo básico para repetições nas linguagens


funcionais.

• São sinónimos: recursividade, recursão, recorrência.


Funções Recursivas (cont.)
Exemplo:
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n-1)

• A primeira equação define que o factorial de zero é um.

• A segunda equação define o factorial de n usando factorial de n -1.

• Logo: o factorial fica definido apenas para inteiros não-negativos.


Funções Recursivas (cont.)
factorial 3
=
3 * factorial 2
=
3 * (2 * factorial 1)
=
3 * (2 * (1 * factorial 0))
=
3 * (2 * (1 * 1))
=
6
Funções Recursivas (cont.)
• Função recursiva é dividida em duas partes:

• Casos base (um ou mais) - que dizem o que fazer em situações simples,
onde não é necessária nenhuma recursividade.

• A resposta pode ser dada de imediato, sem chamar recursivamente a


função sendo definida.
• Garante que a recursividade eventualmente pode parar.

• Casos recursivos (um ou mais) - que são mais gerais, e definem a função
em termos de uma chamada mais simples a si mesma.
Recursão em listas
• Recursão não está restrito a funções com números inteiros, mas
também pode ser usado para definir funções em listas.

• Exemplo: a função que calcula o produto de uma lista de números

product :: Num a => [a] -> a


product [] = 1
product (x:xs) = x * product xs
A função length
• De acordo com o mesmo padrão de recursividade utilizado na função
product podemos definir a função length por recursão:

• Exemplo

length :: [a] -> Int


length [] = 0
length (_:xs) = 1 + length xs
A função length (cont.)
• Exemplo
length [1,2,3]
=
1 + length [2,3]
=
1 + (1 + length [3])
=
1 + (1 + (1 + length []))
=
1 + (1 + (1 + 0))
=
3
A função reverse
• Agora, consideraremos a função reverse que inverte uma lista. Esta
função pode ser definida de acordo com a recursividade como se segue:

• Exemplo

reverse :: [a] -> [a]


reverse [] = []
reverse (x:xs) = reverse xs ++ [x]
Funções com múltiplos argumentos
• Funções com múltiplos argumentos também pode ser definida usando
recursão em mais de um argumento, ao mesmo tempo.

• Exemplo

zip :: [a] → [b] → [(a,b)]


zip [] _ = []
zip _ [] = []
zip (x:xs) (y:ys) = (x,y) : zip xs ys
Funções com múltiplos argumentos
• Exemplo

zip [’a’,’b’,’c’] [1,2,3,4]


=
(’a’,1) : zip [’b’,’c’] [2,3,4]
=
(’a’,1) : (’b’,2) : zip [’c’] [3,4]
=
(’a’,1) : (’b’,2) : (’c’,3) : zip [] [4]
=
(’a’,1) : (’b’,2) : (’c’,3) : []
=
[(’a’,1), (’b’,2), (’c’,3)]
Funções com múltiplos argumentos (cont.)
• Exemplo

drop :: Int -> [a] -> [a]


drop 0 xs = xs
drop n [] = []
drop n (x:xs) | n>0 = drop (n-1) xs
Recursão mútua
• Recursão múltipla é quando uma função é aplicada mais de uma vez em
sua própria definição.

• Por exemplo, recordar a sequência de Fibonacci 0, 1, 1, 2, 3, 5,8, 13, ...

fib :: Int -> Int


fib 0 = 0
fib 1 = 1
fib 2 = 1
fib n = fib (n-2) + fib (n-1)
Recursão mútua (cont.)
• Podemos também definir duas ou mais funções que dependem
mutuamente umas das outras.

• As funções da biblioteca even (par) e odd (ímpar), geralmente são


definidas usando o resto da divisão por dois.
even :: Int -> Bool
even 0 = True
even n | n>0 = odd (n-1)

odd :: Int -> Bool


odd 0 = False
odd n | n>0 = even (n-1)

Você também pode gostar