Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Aula 04 - Variáveis e mais recursividade
Olá Pessoal, desculpem a demora, mas estamos de volta!
Hoje já vamos começar a fazer coisas mais úteis para o 'projeto' final.
Variáveis
Em Haskell, podemos trabalhar com uma espécie de variáveis, a forma mais fácil de explicar é com exemplos.
f :: Int -> Int -> Int
f a b = let c = a + b
in c*2
Ou
f :: Int -> Int -> Int
f a b = c * 2
where c = a + b
Também é válido.
A diferença entre o 'let' e o 'where' é o escopo.
O let é mais restrito, e as coisas ficam apenas visíveis naquele ramo, já o where fornece informação para todas as condições.
Por exemplo (nota: '++' concatena listas):
g :: Int -> [Int] -> Bool
g a l | a == 0 = aux l
| otherwise = aux (l ++ [0])
where
aux :: [a] -> Bool
aux n = faz_qualquer_coisa_com_n
A função aux está visível tanto para o sub-ramo onde a é zero, quanto para o outro.
A declaração com lets não permite isso.
Outro recurso interessante é que é possível fazer pattern matching com 'let's e 'where's
Por exemplo, uma possível definição para a função unzip, que pega numa lista com pares e retorna um par de listas:
unzip :: [(a, B)] -> ([a], [b])
unzip [] = [] // caso elementar
unzip ((e1, e2):t) = let (l1, l2) = unzip t // Nós vamos primeiro fazer unzip no resto da lista
in (e1:l1, e2:l2) //E apenas quando toda a lista ja estiver pronta, colocamos os elementos nas listas corretas.
Outro exemplo, a função splitAt, que divide uma lista numa dada posição e retorna um par com duas listas:
splitAt :: Int -> [a] -> ([a], [a])
splitAt 0 a = ([], a) //dividir a lista na posição zero
splitAt n (h:t) = let (l1, l2) = splitAt (n-1) t
in (h:l1, l2)
EXERCÍCIOS:
//Defina a função div, que divide dois números inteiros, usando recursividade
div :: Int -> Int -> Int
//Defina a função mod, que retorna o modulo de dois números inteiros, usando recursividade
mod :: Int -> Int -> Int
//A função divMod pode ser definida da seguinte forma:
divMod :: Int -> Int -> (Int, Int)
divMod a b = (div a b, mod a B)
//Apresente uma definição recursiva para a função divMod
//defina a função insere, que recebe um inteiro e insere-o numa lista ordenada, mantendo-a ordenada.
insere :: Int -> [Int] -> [Int]
//defina a função merge, que recebe duas listas ordenadas e retorna uma lista ordenada, dica: use a função insere
merge :: [Int] -> [Int] -> [Int]
//defina uma função ordena, que ordena uma lista
ordena :: [Int] -> [Int]
//defina a função unzip3, que faz o mesmo que a função unzip, mas com ternos
unzip3 :: [(a, b, c)] -> ([a], [b], [c])
Pessoal, é importante entender muito bem esses conceitos, para partirmos para estruturas de dados e tipos abstratos de dados.
Aconselho que façam os exercícios e postem dúvidas, busquem mais exercícios na internet para resolvê-los.
ATENÇÃO: as funções div, mod, divMod e unzip3 já estão definidas no Haskell, utilizem outros nomes.