Exercícios Práticos: Programação funcional com Haskell
Preparação
Para este exercício você vai precisar do GHC (Glasgow Haskell Compiler), que é composto por um compilador e um interpretador para Haskell. Em http://www.haskell.org/ghc/dist/current/dist/ você encontra o GHC para Linux e Windows. O exemplo abaixo mostra como invocar o interpretador do GHC no Linux:
user@host:~$ ghci GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. Prelude>
Comandos básicos do GHCi
- :load ou :l: carrega um programa
- :quit ou :q ou Ctrl-D: sai do interpretador
Condicionais
- Reescreva a função abaixo usando guardas ('|') e usando o operador 'mod' de forma infixa.
test1 a b = if mod b 3 == 0 then a + b else if mod b 5 == 0 then b - a else a
- Escreva uma função que receba uma nota de 0.0 a 10.0 (Float) como argumento e retorne o conceito correspondente (Char), conforme as regras abaixo. Obs.: operador 'e' em Haskell se escreve '&&'.
- Nota >= 9.0, conceito A
- Nota >= 7.5 e < 9.0, conceito B
- Nota >= 6.0 e < 7.5, conceito C
- Nota >= 4.0 e < 6.0, conceito D
- Nota < 4.0, conceito E
- A função abaixo não funciona para uma lista vazia (deveria retornar ""). Corrija a função usando 'if-then-else'. Depois escreva outra versão da função usando casamento de padrões e a notação ':' para listas.
import Data.Char maiuscula :: [Char] -> [Char] maiuscula lis = toUpper (head lis) : tail lis
Listas
- Reescreva as funções abaixo usando a notação ':' no casamento de padrões com listas.
somatorio :: [Int] -> Int somatorio [] = 0 somatorio lis = head lis + somatorio (tail lis)
tamanho :: [t] -> Int tamanho [] = 0 tamanho lis = 1 + tamanho (tail lis)
quadrados :: (Num n) => [n] -> [n] quadrados [] = [] quadrados lis = head lis * head lis : quadrados (tail lis)
- Observe as declarações de tipos das funções acima. Quais as diferenças entre as formas de declaração?
- Reescreva a função
quadrados
usando a função pré-definidamap
. - O que faz a função abaixo?
adivinhe :: [a] -> a adivinhe [x] = x adivinhe (_:xs) = adivinhe xs
- Mude a endentação da função acima, colocando um espaço à esquerda na última linha. Carregue e execute a função novamente. O que acontece?
- Crie uma função
countChar :: Char -> [Char] -> Int
que retorne o número de vezes que um caracter aparece na string. Use recursão e casamento de padrões. Exemplo de uso:> countChar 'a' "aaaabaa" 6
- Crie uma função
sumN :: Int -> [Int] -> Int
para calcular o somatório dos N primeiros elementos de uma lista de inteiros. Use recursão e casamento de padrões. Exemplo de uso:sumN 3 [1,2,3,4,5] 6
Entrada/Saída
- Teste a função abaixo, que faz saída em Haskell.
main = putStr "Ola Mundo!" -- main = putStr "Ola Mundo!\n" -- main = putStrLn "Ola Mundo!"
- No exercício acima, há 2 outras versões da função escritas como comentários. Teste cada uma dessas versões, retirando os comentários ('--'). Você consegue explicar as diferenças?
- Teste a função abaixo, que faz entrada e saída.
main = do putStr "Digite seu nome: " nome <- getLine putStrLn ("Ola " ++ nome)
- Altere a função acima para mostrar o nome com inicial maiúscula. Use a função
maiuscula
do exercício feito anteriormente.