SlideShare uma empresa Scribd logo
1 de 205
Paradigma Funcional 
Paradigmas de Linguagem de Programação 
3 CC – Unicentro – 2014 
Prof. Tony Alexander Hild
2 
A Crise do Software 
● Como diminuir o tamanho e complexidade dos software 
modernos? 
● Como reduzir o tempo e custo desenvolvimento de 
software? 
● Como aumentar a confiança que os software finalizados 
irão funcionar corretamente?
3 
Solução para a crise 
● Uma abordagem para solucionar a crise de software foi projetar 
novas linguagens de programação que: 
– Permitissem que programas fossem escritos de forma clara, 
concisa e com um alto nível de abstração; 
– Suportassem componentes de software reutilizáveis; 
– Encorajassem o uso de verificação formal; 
– Permitissem prototipagem rápida; 
– Fornecessem ferramentas poderosas para a solução de 
problemas. 
● Linguagens funcionais fornecem um arcabouço particularmente 
elegante para abordar estas metas.
4 
O que é uma Linguagem Funcional? 
● De uma maneira geral: 
– Programação funcional é um estilo de programação 
onde o método básico de programação é a aplicação 
de funções em argumentos; 
– Uma linguagem funcional é aquela que suporta e 
encoraja o estilo funcional;
5 
Exemplo 
● Somando inteiros de 1 a 10 em C#: 
var total = 0; 
for (int i = 0; i < 10; i++) 
{ 
total += i; 
} 
● O método de computação é atribuição de variáveis.
6 
Exemplo 
● Somando inteiros de 1 a 10 em Haskell: 
sum [1..10] 
● O método de computação é aplicação de função.
7 
Histórico 
● 1930: 
– Alonzo Church desenvolveu o 
cálculo lambda (cálculo-λ): 
● Uma teoria de função simples 
mas poderosa. 
● 1950: 
– John McCarthy desenvolve a Lisp, a primeira 
linguagem funcional, com algumas 
influências do cálculo lambda, mas 
mantendo as atribuições de variáveis.
8 
Histórico 
● 1960: 
– Peter Landin desenvolveu a linguagem ISWIM (If 
you see what i mean), a primeira linguagem 
funcional pura, fortemente baseada no cálculo 
lambda, sem atribuições. 
● 1970: 
– John Backus desenvolveu FP, uma 
linguagem funcional que enfatiza 
funções de ordem superior e raciocínio 
sobre programas.
9 
Histórico 
● 1970: 
– Robin Milner e outros criaram ML, a primeira 
linguagem funcional moderna, qual introduziu 
inferência de tipos e tipos polimórficos 
(generics); 
– ML foi concebida como uma linguagem de 
script para realizar provas formais. 
● 1970-1980: 
– David Turner desenvolveu uma 
série de linguagens funcionais 
preguiçosas (lazy), culminando no 
sistema Miranda.
10 
Histórico 
● 1987: 
– Um comitê internacional 
de pesquisadores 
iniciou o 
desenvolvimento de 
Haskell, uma 
linguagem funcional 
lazy padronizada; 
– http://www.haskell.org/h 
ugs/
11 
Histórico 
● 2003: 
– O comitê publica o 
relatório Haskell 98, 
definindo uma definição 
estável da linguagem; 
– http://www.haskell.org/o 
nlinereport/
12 
Haskell - Exemplo 
f [] = [] 
f (x:xs) = f ys ++ [x] ++ f zs 
where 
ys = [ a | a <- xs, a <= x ] 
zs = [ b | b <- xs, b > x ] 
?
13 
Hugs 
● Implementação do Haskell 98, e é o sistema Haskell mais 
utilizado; 
● A natureza interativa do Hugs o torna ideal para os 
propósitos de ensino e prototipagem; 
● Disponível em: 
http://www.haskell.org/hugs/
14 
Iniciando o Hugs 
● Em um sistema Unix, o Hugs pode ser iniciado a partir do 
prompt de comando simplesmente escrevendo-se: 
# hugs 
__ __ __ __ ____ ___ _________________________________________ 
|| || || || || || ||__ Hugs 98: Based on the Haskell 98 standard 
||___|| ||__|| ||__|| __|| Copyright (c) 1994-2005 
||---|| ___|| World Wide Web: http://haskell.org/hugs 
|| || Bugs: http://hackage.haskell.org/trac/hugs 
|| || Version: September 2006 _________________________________________ 
Haskell 98 mode: Restart with command line option -98 to enable extensions 
Type :? for help 
Hugs>
15 
Iniciando o Hugs (2) 
● Hugs> significa que o sistema Hugs está pronto para avaliar uma 
expressão; 
● Por exemplo: 
Hugs> 2+3*4 
14 
Hugs> (2+3)*4 
20 
Hugs> sqrt (3^2 + 4^2) 
5.0
16 
O Prelude padrão 
● Haskell contém uma biblioteca chamada Prelude.hs que 
contém um grande número de funções: 
– Funções numéricas: +, *; 
– Funções em listas.
17 
Funções em listas 
● Seleciona o primeiro elemento de uma lista: 
> head [1,2,3,4,5] 
1 
● Remove o primeiro elemento de uma lista: 
> tail [1,2,3,4,5] 
[2,3,4,5] 
● Seleciona o enésimo elemento de uma lista: 
> [1,2,3,4,5] !! 2 
3 
● Seleciona os primeiros n elementos de uma lista: 
> take 3 [1,2,3,4,5] 
[1,2,3]
18 
Funções em listas (2) 
● Remove os primeiros n elementos de uma lista: 
> drop 3 [1,2,3,4,5] 
[4,5] 
● Calcula o comprimento de uma lista: 
> length [1,2,3,4,5] 
5 
● Calcula a soma dos elementos de uma lista: 
> sum [1,2,3,4,5] 
15
19 
Funções em listas (3) 
● Calcula o produto dos elementos de uma lista: 
> product [1,2,3,4,5] 
120 
● Junta duas listas: 
> [1,2,3] ++ [4,5] 
[1,2,3,4,5] 
● Reverte uma lista: 
> reverse [1,2,3,4,5] 
[5,4,3,2,1]
20 
Aplicação de funções 
● Na matemática, a aplicação de uma função é denotada 
usando parêntesis, e a multiplicação é geralmente 
denotada usando justaposição ou espaço. 
– f(a,b) + c d 
Aplica a função f à a e b, e adiciona o resultado 
Aplica a função f à a e b, e adiciona o resultado 
o produto ao produto de c e d. 
o produto ao produto de c e d.
21 
Aplicação de funções (2) 
● Em Haskell, a aplicação de funções é denotada usando 
espaço, e a multiplicação é denotada usando *: 
– f a b + c*d 
Como no exemplo anterior, só que agora na 
Como no exemplo anterior, só que agora na 
sintaxe Haskell 
sintaxe Haskell
22 
Aplicação de funções (2) 
● Também, a aplicação de funções tem precedência sobre 
todos os outros operadores: 
– f a + b 
Significa Significa ((ff aa)) ++ bb,, aaoo ccoonnttrráárriioo ddee ff ((aa ++ bb))
23 
Aplicação de funções (Exemplos) 
Matemática Haskell 
f(x) f x 
f(x,y) f x y 
f(g(x)) f (g x) 
f(x,g(y)) f x (g y) 
f(x)g(y) f x * g y
24 
Scripts em Haskell 
● Apesar de haver funções na biblioteca padrão (prelude), é 
possível definir funções próprias; 
● Novas funções são definidas em um script, um arquivo de 
texto contendo uma sequência de definições; 
● Por convenção, scripts Haskell possuem extensão .hs.
25 
Meu primeiro script 
● É útil manter duas janelas abertas ao programar em 
Haskell. Uma para o script o outra para o Hugs; 
● Abra um editor, digite as duas expressões e salve com o 
nome teste.hs: 
double x = x + x 
quadruple x = double (double x)
26 
Meu primeiro script (2) 
● Deixe o editor aberto e inicie o Hugs com: 
> hugs teste.hs 
ou 
> hugs 
> :load teste.hs
27 
Meu primeiro script (3) 
● Agora Prelude.hs e teste.hs estão carregados, e as 
funções dos dois scripts podem ser usadas: 
> quadruple 10 
40 
> take (double 2) [1,2,3,4,5,6] 
[1,2,3,4]
28 
Meu primeiro script (4) 
● Mantendo o Hugs aberto, retorne ao editor, adicione as 
definições abaixo, salve e digite :reload no Hugs: 
factorial n = product [1..n] 
average ns = sum ns `div` length ns 
● Nota: 
– 
● div é cercado por aspas invertidas (crase); 
● x `f` y é apenas um syntactic sugar para f x y. 
● div é cercado por aspas invertidas (crase); 
● x `f` y é apenas um syntactic sugar para f x y.
29 
Meu primeiro script (5) 
> factorial 10 
3628800 
> average [1,2,3,4,5] 
[1,2,3]
30 
Requisitos para nomes 
● Nomes de funções e argumentos devem iniciar em caixa 
baixa: 
myFun fun1 arg_2 x' 
● Por convensão, argumentos de lista geralmente possuem 
o sufixo s nos seus nomes (notação húngara): 
xs ns nss
31 
A regra do layout 
a = 10 
b = 20 
c = 30 
a = 10 
b = 20 
c = 30 
a = 10 
b = 20 
c = 30
32 
A regra do layout (2) 
a = b + c 
where 
b = 1 
C = 2 
d = a * 2 
a = b + c 
where 
{b = 1 
c = 2} 
d = a * 2 
Mesmo que 
AAggrruuppaammeenntoto i mimpplílcícitioto AAggrruuppaammeenntoto e exxpplílcícitioto
33 
Exercícios 
● 1. Teste os slides 17-19 e 25-29 usando Hugs; 
● 2. Corrija os erros do programa abaixo, e teste sua 
solução usando Hugs. 
N = a 'div' lenght xs 
where 
a = 10 
xs = [1,2,3,4,5]
34 
Exercícios 
3.Tente reescrever a função last, que seleciona o último 
elemento de uma lista, usando as funções vistas 
anteriormente; 
4.Você consegue pensar em outra solução? 
3.Similarmente, reescreva a função init, que remove o último 
elemento de uma lista.
35 
O que é um tipo? 
Um tipo é um nome para uma coleção de valores 
relacionados. Por exemplo, o tipo básico 
Bool 
contém dois valores lógicos: 
False True
36 
Erros de tipo 
● Aplicar um função à um ou mais argumentos do tipo 
errado é chamado erro de tipo. 
> 1 + False 
Error 
1 é um número e False é um valor lógico, mas 
1 é um número e False é um valor lógico, mas 
+ requer dois números 
+ requer dois números
37 
Tipos em Haskell 
● Se ao avaliar uma expressão e produzir um valor do tipo t, 
então e tem o tipo t, escrito: 
e :: t 
● Toda expressão bem formada tem um tipo, que pode ser 
automaticamente calculado em tempo de compilação 
usando um processo chamado inferência de tipo.
38 
Tipos em Haskell (2) 
● Todos os erros de tipo são verificados em tempo de 
compilação, o que torna os programas seguros e 
rápidos, removendo a necessidade de checagem de tipo 
em tempo de execução; 
● No Hugs, o comando :type calcula o tipo de uma 
expressão, sem avaliá-la. 
> not False 
True 
> :type not False 
not False :: Bool
39 
Tipos básicos em Haskell 
Bool Valores lógicos 
Char Caracteres únicos 
String String (fio) de caracteres 
Int Inteiros de precisão fixa 
Integer Inteiros de precisão arbitrária 
Float Número de ponto flutuante
40 
Tipos Lista 
● Uma lista é uma sequência de valores do mesmo tipo: 
[False,True,False] :: [Bool] 
['a','b','c','d'] :: [Char] 
● De maneria geral: 
[t] é o tipo de listas de elementos do tipo t.
41 
Tipos Lista (2) 
● Nota: 
– O tipo das listas não diz nada sobre o seu tamanho 
[False,True] :: [Bool] 
[False,True,False] :: [Bool] 
– O tipo dos elementos não tem restrições. Por exemplo, 
é possível criar listas de listas: 
[['a'],['b','c']] :: [[Char]]
42 
Tipos Tupla 
● Uma tupla é uma sequência de valores de tipos 
diferentes: 
(False,True) :: (Bool,Bool) 
(False,'a',True) :: (Bool,Char,Bool) 
● De modo geral: 
– (t1,t2,...,tn) é o tipo de n-tuplas quais os iésimos 
componentes têm o tipo ti para qualquer i em 1..n.
43 
Tipos Tupla (2) 
● Nota: 
– O tipo de uma tupla codifica seu tamanho: 
(False,True) :: (Bool,Bool) 
(False,True,False) :: (Bool,Bool,Bool) 
– Não há restrições para o tipo dos componentes: 
('a',(False,'b')) :: (Char,(Bool,Char)) 
(True,['a','b']) :: (Bool,[Char])
44 
Tipos Função 
● Uma função é um mapeamento de valores de um tipo 
para valores de outro tipo: 
not :: Bool → Bool 
isDigit :: Char → Bool 
● De maneira geral: 
– t1 → t2 é o tipo das funções que mapeia valores do tipo 
t1 para valores do tipo t2.
45 
Tipos Função (2) 
● Nota: 
– A flecha → é digitada no teclado como ->; 
– Não há restrições para o tipo de argumento e 
resultados. Por exemplo, funções com múltiplos 
argumentos ou resultados são possíveis usando listas 
ou tuplas. 
add :: (Int,Int) → Int 
add (x,y) = x + y 
zeroto :: Int → [Int] 
zeroto n = [0..n]
46 
Funções Arranjadas (Curried) 
● Funções com múltiplos argumentos que retornam 
funções como resultado: 
add' :: Int → (Int → Int) 
add' x y :: x + y 
add' toma um valor inteiro x e retorna uma função 
add' x. Por sua vez, esta função toma um inteiro y 
add' toma um valor inteiro x e retorna uma função 
add' x. Por sua vez, esta função toma um inteiro y 
e retorna o resultado de x + y. 
e retorna o resultado de x + y.
47 
Funções Arranjadas (Curried) (2) 
● Nota: 
– add e add' produzem o mesmo resultado final, mas add 
toma seus dois argumentos ao mesmo tempo, 
enquanto add' toma um de cada vez: 
add :: (Int,Int) → Int 
add' :: Int → (Int → Int) 
● Funções que tomam um argumento por vez são 
chamadas funções arranjadas ou curried, em homenagem 
a Haskell Curry.
48 
Funções Arranjadas (Curried) (3) 
● Funções com mais de dois argumentos podem ser 
arranjadas retornando funções aninhadas: 
mult :: Int → (Int → (Int → Int)) 
mult x y z = x*y*z 
mult toma um inteiro x e retorna uma função mult x, que 
por sua vez toma um inteiro y e retorna uma função mult 
mult toma um inteiro x e retorna uma função mult x, que 
por sua vez toma um inteiro y e retorna uma função mult 
x y, que finalmente toma um inteiro z e retorna o 
x y, que finalmente toma um inteiro z e retorna o 
resultado x * y * z. 
resultado x * y * z.
49 
Por que Currying é útil? 
● Funções curried são mais flexíveis que funções em tuplas, 
porque funções úteis muitas vezes podem ser construídas 
aplicando parcialmente uma função curried. 
● Por exemplo: 
add' 1 :: Int → Int 
take 5 :: [Int] → [Int] 
drop 5 :: [Int] → [Int]
50 
Convensões de curring 
● Para evitar excesso de parênteses quando usa-se funções 
curried, duas convenções simples são adotadas: 
– A flecha → associa à direita. 
Int → Int → Int → Int 
SSiiggnniiffiiccaa IInntt →→ ((IInntt →→ ((IInntt →→ IInntt))))
51 
Convensões de curring (2) 
● Por consequência, é natural aplicar uma função 
associando a esquerda. 
mult x y z 
SSiiggnniifficicaa ((((mmuultlt xx)) yy)) zz 
● A não ser que tuplas sejam requeridas, todas as funções 
em Haskell são normalmente definidas na forma curried.
52 
Funções Polimórficas 
● Uma função é chamada polimórfica (“de muitas formas”) 
se seu tipo contém uma ou mais variáveis de tipo. 
length :: [a] → Int 
Para qualquer tipo a, length toma uma lista 
de valores do tipo a e retorna um inteiro. 
Para qualquer tipo a, length toma uma lista 
de valores do tipo a e retorna um inteiro.
53 
Funções Polimórficas (2) 
● Nota: 
– Variáveis de tipo podem ser instanciadas para 
diferentes tipos em diferentes circunstâncias: 
> length [False,True] 
2 
> length [1,2,3,4] 
4 
aa == BBooooll 
aa == IInntt 
– Variáveis de tipo devem começar com letras 
minúsculas, e usualmente são nomeadas a, b, c, etc.
54 
Funções Polimórficas (3) 
● Várias funções do prelude são polimórficas: 
fst :: (a,b) → a 
head :: [a] → a 
take :: Int → [a] → [a] 
zip :: [a] → [b] → [(a,b)] 
id :: a → a
Char não é um 
tipo numérico 
55 
Funções Polimórficas (4) 
● Variáveis de tipo restrito podem ser instanciadas para 
qualquer tipo que satisfaça a restrição. 
> sum [1,2,3] 
6 
> sum [1.1,2.2,3.3] 
6.6 
> sum ['a','b','c'] 
ERROR 
aa == IInntt 
aa == FFllooaatt 
Char não é um 
tipo numérico
56 
Funções Polimórficas (5) 
● Haskell possui várias classes de tipo, incluindo: 
– Num – Tipos numéricos 
– Eq – Tipos de igualdade 
– Ord – Tipos de relação (ordenação) 
● Por exemplo: 
(+) :: Num a => a → a → a 
(==) :: Eq a => a → a → Bool 
(<) :: Ord a => a → a → Bool
57 
Dicas e Sugestões 
● Ao definir uma nova função em Haskell, é útil iniciar 
escrevendo seu tipo; 
● Em um script, é uma boa prática definir o tipo de todas as 
novas funções; 
● Quando definir os tipos de funções polimórficas que 
utilizam números, igualdades ou relações, tenha cuidado 
em incluir as classes de restrições necessárias.
58 
Dicas e Sugestões 
add :: Num a => a -> a -> a 
add x y = x + y
59 
Exercícios 
● Quais são os tipos dos seguintes valores? 
['a','b','c'] 
('a','b','c') 
[(False,'0'),(True,'1')] 
[(False,True),('0','1')] 
[tail,init,reverse]
60 
Exercícios 
● Quais são os tipos das seguintes funções? 
second xs = head (tail xs) 
swap (x,y) = (y,x) 
pair x y = (x,y) 
double x = x*2 
palindrome xs = reverse xs == xs 
twice f x = f(f x) 
● Verifique suas respostas usando o Hugs.
61 
Expressões Condicionais 
● Na maioria das linguagens de programação, funções 
podem ser definidas usando expressões condicionais. 
abs :: Int → Int 
abs n = if n >= 0 then n else -n 
abs toma um inteiro n se n for não-negativo, 
abs toma um inteiro n se n for não-negativo, 
senão, retorna -n. 
senão, retorna -n.
62 
Expressões Condicionais 
● Expressões condicionais podem ser aninhadas: 
signum :: Int → Int 
signum n = if n < 0 then -1 else 
● Nota: 
if n == 0 then 0 else 1 
– Em Haskell, expressões condicionais sempre devem 
ter o desvio senão (else), que evita ambiguidades com 
expressões aninhadas.
63 
Equações restritas (Guarded Equations) 
● Com alternativa para expressões, funções também podem 
ser definidas usado equações restritas: 
abs n | n >= 0 = n 
| otherwise = -n 
Como o anterior, m Como o anterior, maass uussaannddoo gguuaarrddeedd..
64 
Equações restritas (Guarded Equations) 
● Equações restritas podem ser usadas para simplificar a 
leitura de definições que envolvem múltiplas condições: 
● Nota: 
signum n | n < 0 = -1 
| n == 0 = 0 
| otherwise = 1 
– A condição otherwise é definida no prelude por 
otherwise = True.
65 
Pattern Matching 
● Muitas funções possuem uma definição mais clara 
utilizando pattern matching (casamento de padrões) nos 
seus argumentos: 
not :: Bool → Bool 
not False = True 
not True = False 
not mapeia False para not mapeia False para TTrruuee,, ee TTrruuee ppaarraa FFaallssee
66 
Pattern Matching (2) 
(&&) :: Bool → Bool → Bool 
True && True = True 
_ && _ = False 
WWiillddccaarrdd 
(&&) :: Bool → Bool → Bool 
True && x = True , x == True 
= False , x == False 
False && x = False , x == False 
= False , x == True
67 
Pattern Matching (3) 
(&&) :: Bool → Bool → Bool 
True && True = True 
True && False = False 
False && True = False 
False && False = False 
(&&) :: Bool → Bool → Bool 
True && b = b 
False && _ = False
68 
Pattern Matching (4) 
● Padrões são casados segundo a ordem top → bottom, left 
→ rigth. Por exemplo, a seguinte definição sempre retorna 
False: 
_ && _ = False 
True && True = True 
● Padrões não podem repetir variáveis. Por exemplo, a 
seguinte definição causa um erro: 
b && b = b 
_ && _ = False
69 
Padrões de Listas 
● Internamente, toda lista não-vazia é construída pelo uso 
repetido do operador (:) chamado “cons” que adiciona 
um elemento ao início da lista. 
[1,2,3,4] 
SSiiggnniiffiiccaa 11::((22::((33::((44::[[]]))))))
70 
Padrões de Listas 
● Funções em listas podem ser definidas utilizando padrões 
x:xs. 
head :: [a] → a 
head (x:_) = x 
tail :: [a] → [a] 
tail (_:xs) :: xs 
head e tail mapeia qualquer lista não-vazia para 
head e tail mapeia qualquer lista não-vazia para 
seus primeiros e últimos elementos 
seus primeiros e últimos elementos
71 
Padrões de Listas 
● Nota: 
– O padrão x:xs somente casa listas não-vazias: 
> head [] 
Error 
– Padrões x:xs devem ser parentesados, por que a 
aplicação do padrão tem prioridade sobre (:). Por 
exemplo, a seguinte definição retorna um erro: 
head x:_ = x
72 
Padrões de Inteiros 
● Como na matemática, funções em inteiros podem ser 
definidas usando o padrão n+k, onde n é uma variável 
inteira e k>0 é uma constante inteira. 
pred :: Int → Int 
pred (n+1) = n 
pred mapeia qualquer inteiro 
positivo para seu predecessor 
pred mapeia qualquer inteiro 
positivo para seu predecessor
73 
Padrões de Inteiros 
fac :: Int → Int 
fac 0 = 1 
fac (n+1) = n + (fac n)
74 
Padrões de Inteiros 
● Nota: 
– Padrões n+k casam somente inteiros ≥ k. 
> pred 0 
Error 
– Padrões n+k devem ser parentesados, porque a 
aplicação tem prioridade sobre +. Por exemplo, a 
seguinte definição resulta em um erro: 
pred n+1 = n
75 
Expressões Lambda 
● Funções podem ser construídas sem serem nomeadas 
usado expressões lambda. 
λx → x + x 
uma função sem nome que 
toma um número x e retorna o 
uma função sem nome que 
toma um número x e retorna o 
resultado x+x 
resultado x+x
76 
Expressões Lambda 
● Em Haskell: 
Int -> Int 
x -> x + x
77 
Expressões Lambda 
● Nota: 
– O símbolo λ é a letra Grega lambda, e é escrita no 
teclado com ; 
– Na matemática, funções sem nome são usualmente 
denotadas usado o símbolo ↦, como em x ↦ x + x; 
– Em Haskell, o uso do símbolo λ para funções sem 
nome vem do cálculo lambda, a teoria de funções no 
qual Haskell é baseado.
78 
Por que Lambdas são úteis? 
Expressões lambda poder ser usadas para dar um 
significado formal para funções definidas com currying. 
Por exemplo: 
significa 
add x y = x + y 
add = λx → (λy → x + y)
79 
Por que Lambdas são úteis? 
Expressões lambda também são úteis ao definir funções que 
retornam funções como resultado. 
Por exemplo: 
const :: a → b → a 
const x _ = x 
é mais naturalmente definido por 
const :: a → (b → a ) 
const x = λ_ x → x
80 
Por que Lambdas são úteis? 
Expressões lambda poder ser usadas para evitar dar nomes 
a funções que são referenciadas uma vez apenas. 
Por exemplo: 
odds n = map f [0..n-1] 
where 
f x = x*2 + 1 
Pode ser simplificado para 
odds n = map (λx → x*2 + 1) [0..n-1]
81 
Seções 
● Um operador escrito entre seus dois argumentos pode ser 
convertido em uma função curried escrita antes de seus 
dois argumentos usando parênteses. 
● Por exemplo: 
> 1 + 2 
3 
> (+) 1 2 
3
82 
Seções 
● Esta convenção ainda permite que um dos argumentos do 
operador seja incluído nos parênteses. 
● Por exemplo: 
> (1+) 2 
3 
> (+2) 1 
3 
● Geralmente, se é ⊕ um operador, então funções na forma 
(⊕), (x⊕) e (⊕y) são chamadas seções.
83 
Por que seções são úteis? 
Funções úteis as vezes podem ser construídas de uma 
maneira simples utilizando seções. 
Por exemplo: 
(1+) – função sucessor 
(1/) – função recíproca 
(*2) – função para dobrar 
(/2) – função para dividir ao meio
84 
Exercícios 
1.Considere a função safetail que tem o mesmo 
comportamento da função tail, exceto por safetail mapear 
lista vazia para lista vazia, sendo que tail retorna um erro 
neste caso. 
– Defina safetail usando: 
● Uma expressão condicional; 
● Uma expressão abrigada (guarded); 
● Casamento de padrões. 
– Dica: a função null :: [a] → Bool pode ser usada para 
verificar se uma lista é vazia.
85 
Exercícios 
2.Crie três possíveis definições para o operador lógica (||) 
usando casamento de padrões; 
3.Redefina a seguinte versão de (&&) usando expressões 
condicionais ao invés de casamento de padrões: 
True && True = True 
_ && _ = False 
6.Faça o mesmo para a seguinte versão: 
True && b = b 
False && _ = False
86 
Listas por Compreensão (List Comprehensions) 
● Na matemática, a notação por compreensão pode ser 
usada para construir novos conjuntos a partir de conjuntos 
antigos. 
O conjunto {1,4,9,16,25} de todos os números 
x2 tal que x seja um elemento do conjunto {1...5} 
O conjunto {1,4,9,16,25} de todos os números 
x2 tal que x seja um elemento do conjunto {1...5}
87 
Listas por Compreensão (2) 
● Em Haskell, um notação por compreensão similar pode 
ser usada para construir novas listas a partir de listas 
antigas. 
[x^2 | x ← [1..5]] 
A lista [1,4,9,16,25] de todos os números x^2 
tal que x seja um elemento da lista [1..5] 
A lista [1,4,9,16,25] de todos os números x^2 
tal que x seja um elemento da lista [1..5]
88 
Listas por Compreensão (3) 
● Nota: 
– A expressão x ← [1..5] é chamada geradora, pois ela 
define como gerar os valores para x; 
– Compreensões podem ter várias geradoras, separadas 
por vírgula. Por exemplo: 
> [(x,y) | x ← [1,2,3], y ← [4,5]] 
[(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)]
89 
Listas por Compreensão (4) 
● Nota: 
– Alterando a ordem das geradoras altera a ordem dos 
elementos na lista final: 
> [(x,y) | x ← [4,5], y ← [1,2,3]] 
[(1,4),(2,4),(3,4),(1,5),(2,4),(3,5)] 
– Múltiplas geradoras são como laços aninhados, sendo 
as últimas geradoras são os laços mais profundos onde 
os valores das variáveis se alteram com mais frequência.
90 
Listas por Compreensão (5) 
● Por exemplo: 
> [(x,y) | x ← [4,5], y ← [1,2,3]] 
[(1,4),(2,4),(3,4),(1,5),(2,4),(3,5)] 
x ← [1,2,3] é a última geradora, sendo assim 
x ← [1,2,3] é a última geradora, sendo assim 
o valor do componente x 
se altera com mais frequência 
o valor do componente x 
se altera com mais frequência
91 
Geradoras Dependentes 
● As últimas expressões geradoras podem depender de 
variáveis introduzidas nas primeiras geradoras. 
[(x,y) | x ← [1..3], y ← [x..3]] 
A lista [(1,1),(1,2),(1,3),(2,2),(2,3),(3,3)] 
de todos os pares dos números (x,y) 
A lista [(1,1),(1,2),(1,3),(2,2),(2,3),(3,3)] 
de todos os pares dos números (x,y) 
tal que x,y sejam elementos da lista [1..3] e y >= x 
tal que x,y sejam elementos da lista [1..3] e y >= x
92 
Geradoras Dependentes 
● Usando uma expressão geradora dependente pode-se 
definir uma função de biblioteca que concatena uma lista 
de listas. 
concat :: [[a]] → [a] 
concat xss = [x | xs ← xss, x ← xs] 
● Por exemplo: 
concat [[1,2,3],[4,5],[6]] 
[1,2,3,4,5,6]
93 
Guards 
● Listas por compreensão podem usar “guards” para 
restringir o valor produzido pelas primeiras geradoras. 
[x | x ← [1..10], even x] 
A lista [2,4,6,8,10] 
A lista [2,4,6,8,10] 
de todos os números x tal que x seja 
um elemento da lista [1..10] e x seja par 
de todos os números x tal que x seja 
um elemento da lista [1..10] e x seja par
[x | x <- [1..n], n `mod` x == 0] 
94 
Guards 
● Usando “guards” é possível definir uma função que 
mapeia um número inteiro positivo para sua lista de 
fatores: 
factors :: Int -> [Int] 
factors n = 
● Por exemplo: 
> factors 15 
[1,3,5,15]
95 
Guards 
● Um inteiro positivo é primo se seus únicos fatores forem 1 
e ele mesmo. Sendo assim, usando factors é possível 
definir uma função que decide se um número é primo: 
prime :: Int → Bool 
prime n = factors n == [1,n] 
● Por exemplo: 
> prime 15 
False 
> prime 7 
True
96 
Guards 
● Agora, usando “guards” é possível definir uma função que 
retorna a lista de todos os primos até um dado limite: 
primes ::Int → [Int] 
primes n = [x | x ← [2..n], prime x] 
● Por exemplo: 
> primes 40 
[2,3,5,7,11,13,17,19,23,29,31,37]
97 
A função Zip 
● Uma função de biblioteca muito útil, qual mapeia duas 
listas para uma lista de pares de seus elementos 
correspondentes. 
zip :: [a] → [b] → [(a,b)] 
● Por exemplo: 
> zip ['a','b','c'][1,2,3,4] 
[('a',1),('b',2),('c',3)]
98 
A função Zip 
● Usando zip é possível definir uma função que retorna uma 
lista de todos os pares de elementos adjacentes de outra 
lista: 
pairs :: [a] → [(a,a)] 
pairs xs = zip xs (tail xs) 
● Por exemplo: 
> pairs [1,2,3,4] 
[(1,2),(2,3),(3,4)]
● Usando pairs é possível definir uma função que decide se 
os elementos de uma lista estão ordenados: 
99 
sorted :: Ord a => [a] → Bool 
sorted xs = 
and [x <= y | (x,y) ← pairs xs] 
● Por exemplo: 
> sorted [1,2,3,4] 
True 
> sorted [1,3,2,4] 
False
● Usando zip é possível definir uma função que retorna uma 
lista de todas as posições de um valor em uma lista: 
100 
positions :: Eq a => a → [a] → [Int] 
positions x xs = 
[i | (x',i) ← zip xs [0..n], x == x'] 
where n = length xs - 1 
● Por exemplo: 
> positions 0 [1,0,0,1,0,1,1,0] 
[1,2,4,7]
101 
Compreensões em String 
● Uma string é uma sequência de caracteres cercadas por 
aspas duplas. Internamente, no entanto, strings são 
representadas como listas de caracteres. 
“abc” :: String 
Significa Significa [['a'a',','b'b',','c'c']'] :::: [[CChhaarr]]
102 
● Similarmente, compreensões em strings podem ser 
usadas para definir funções em strings como, por 
exemplo, uma função que conta as letras minúsculas 
(caixa-baixa) em uma string: 
lowers :: String → Int 
lowers xs = 
length [x | x ← xs, isLower x] 
● Por exemplo: 
> lowers “Haskell” 
6
103 
Exercícios 
1. Um tripla (x,y,z) de inteiros positivos é chamada de 
pitagórica se x² + y² = z². Usando uma compreensão 
em lista, defina a função 
pyths :: Int → [(Int,Int,Int)] 
que mapeia um inteiro n para todas as triplas com 
componentes em [1..n]. Por exemplo: 
> pyths 5 
[(3,4,5),(4,3,5)]
104 
Exercícios 
2. Um inteiro positivo é perfeito se for igual à soma de 
todos os seus fatores, excluindo o próprio número. 
Usando uma compreensão de lista, defina uma 
função 
perfects :: Int → [Int] 
que retorne a lista de todos os números perfeitos até um 
dado limite. Por exemplo: 
> perfects 500 
[6,28,496]
105 
Leitura 
Hughes, John. Why Functional Programming Matters 
http://www.cse.chalmers.se/~rjmh/Papers/whyfp.pdf
106 
Funções recursivas 
● Como visto, muitas funções podem ser definidas em 
termos de outras funções. 
factorial :: Int → Int 
factorial n = product [1..n] 
factorial mapeia qualquer inteiro n para o produto dos 
factorial mapeia qualquer inteiro n para o produto dos 
inteiros entre 1 e n 
inteiros entre 1 e n
107 
Funções recursivas (2) 
● Expressões são avaliadas em um processo passo-a-passo 
de aplicação de funções em seus argumentos. 
● Por exemplo: 
factorial 4 
= 
product [1..4] 
= 
product [1,2,3,4] 
= 
1*2*3*4 
= 
24
108 
Funções recursivas (3) 
product :: [Int] → Int 
product [] = 1 
product (x:xs) = x * product xs 
.... 
fact 4 [1,2,3,4] 
= 
product (1:(2:(3:(4:[])))) 
= 
1 * product (2:(3:(4:[]))) 
. 
. 
.
109 
Funções recursivas (4) 
● Em Haskell, funções podem ser definidas em termos delas 
mesmas. Tal funções são chamadas recursivas. 
factorial 0 = 1 
factorial (n+1) = (n+1) * factorial n 
factorial mapeia 0 para 1, e qualquer outro inteiro 
positivo para o produto dele mesmo com o fatorial de 
factorial mapeia 0 para 1, e qualquer outro inteiro 
positivo para o produto dele mesmo com o fatorial de 
seu predecessor. 
seu predecessor.
110 
Funções recursivas (5) 
factorial 3 
= 
3 * factorial 2 
= 
3 * (2 * factorial 1) 
= 
3 * (2 * (1 * factorial 0)) 
= 
3 * (2 * (1 * 1)) 
= 
3 * (2 * 1) 
= 
3 * 2 
= 
6
111 
Funções recursivas (nota) 
● factorial 0 = 1 é apropriado pois 1 é o valor identidade da 
multiplicação: 1*x = x = x*1 
● A definição da função recursiva diverge em inteiros < 0 
porque o caso base nunca é alcançado: 
> factorial (-1) 
Error: Control stack overflow
112 
Porque recursão é útil 
● Algumas funções, como factorial, são mais simples de 
definir em termos de outras funções. 
● Como visto, no entanto, muitas funções podem ser 
naturalmente definidas em termos delas mesmas. 
● Propriedades de funções definidas usando recursão 
podem ser provadas usando uma simples porém 
poderosa técnica matemática de indução.
113 
Recursões em listas 
● Recursão não se restringe à números, mas também pode 
ser usado para definir funções em listas. 
product :: [Int] → Int 
product [] = 1 
product (x:xs) = x * product xs 
product mapeia a lista vazia para 1, e qualquer outra 
lista não-vazia para sua cabeça multiplicada pelo 
product mapeia a lista vazia para 1, e qualquer outra 
lista não-vazia para sua cabeça multiplicada pelo 
produto de sua calda. 
produto de sua calda.
114 
Recursões em listas (2) 
product [2,3,4] 
= 
2 * product [3,4] 
= 
2 * (3 * product[4]) 
= 
2 * (3 * ( * 4 * product[]) 
= 
2 * (3 * (4 * 1)) 
= 
24
115 
Recursões em listas (3) 
● Usando o mesmo padrão de recursão como em product 
pode-se definir a função length em listas. 
length :: [a] → Int 
length [] = 0 
length (_:xs) = 1 + length xs 
length mapeia um lista vazia para 0, e qualquer outra 
lista não-vazia para o sucessor do comprimento de 
length mapeia um lista vazia para 0, e qualquer outra 
lista não-vazia para o sucessor do comprimento de 
sua calda. 
sua calda.
116 
Recursões em listas (4) 
length [1,2,3] 
= 
1 + length [2,3] 
= 
1 + (1 + length [3]) 
= 
1 + (1 + (1 + (length [])) 
= 
1 + (1 + (1 + (0)) 
= 
3
117 
Recursões em listas (5) 
● Usando um padrão similar de recursão pode-se definir a 
função reverse em listas. 
reverse :: [a] → [a] 
reverse [] = [] 
reverse (x:xs) = reverse xs ++ [x] 
reverse mapeia um lista vazia outra lista vazia, e 
qualquer outra lista não-vazia para o reverso da sua 
reverse mapeia um lista vazia outra lista vazia, e 
qualquer outra lista não-vazia para o reverso da sua 
calda concatenada com a cabeça. 
calda concatenada com a cabeça.
118 
Recursões em listas (4) 
reverse [1,2,3] 
= 
reverse [2,3] ++ [1] 
= 
(reverse [3] ++ [2]) ++ [1] 
= 
((reverse [] ++ [3] ++ [2]) ++ [1] 
= 
(([] ++ [3] ++ [2]) ++ [1] 
= 
[3,2,1]
119 
Múltiplos argumentos em recursão 
● Funções com mais de um argumento também podem ser 
definidas usando recursão. 
● Por exemplo, zipping os elementos de duas listas: 
zip :: [a] → [b] → [(a,b)] 
zip [] _ = [] 
zip _ [] = [] 
zip (x:xs) (y:ys) = (x,y) : zip xs ys
120 
Múltiplos argumentos em recursão (2) 
● Remover os primeiros n elementos de uma lista: 
drop :: Int → [a] → [a] 
drop 0 xs = xs 
drop (n+1) [] = [] 
drop (n+1) (_:xs) = drop n xs 
● Concatenar duas listas: 
(++) :: [a] → [a] → [a] 
[] ++ ys = ys 
(x:xs) ++ ys = x : (xs ++ ys)
121 
Quicksort 
● O algoritmo quicksort para ordenar uma lista de inteiros 
pode ser especificado pelas duas regras seguintes: 
– Uma lista vazia já está ordenada; 
– Listas não-vazias podem ser ordenadas ordenando os 
valores da cauda <= à cabeça, ordenando os valores 
da cauda > que a cabeça, e concatenando as duas 
listas resultantes em cada lado do valor da cabeça.
122 
Quicksort (2) 
● Usando recursão, esta especificação pode ser traduzida 
diretamente para uma implementação: 
qsort :: [Int] -> [Int] 
qsort [] = [] 
qsort (x:xs) = 
qsort menores ++ [x] ++ qsort maiores 
where 
menores = [a | a <- xs, a <= x] 
maiores = [b | b <- xs, b > x] 
Nota: 
Esta é provavelmente a implementação mais 
simples de quicksort em qualquer linguagem de 
programação. 
Nota: 
Esta é provavelmente a implementação mais 
simples de quicksort em qualquer linguagem de 
programação.
123 
Quicksort (3) 
qq [[33,,22,,44,,11,,55]] 
qq [[22,,11]] ++++ [[33]] ++++ qq [[44,,55]] 
qq [[11]] ++++ [[22]] ++++ qq [[]] qq [[]] ++++ [[44]] ++++ qq [[55]] 
[[11]] [[]] [[]] [[55]]
124 
Exercícios 
● Sem olhar no prelude padrão, defina as seguinte biblioteca de funções usando 
recursão: 
– Verificar se todos os valores em uma lista são verdadeiros: 
and :: [Bool] → Bool 
– Concatenar uma lista de listas: 
concat :: [[a]] → [a] 
– Produzir uma lista com n elementos idênticos: 
replicate :: Int → a → [a] 
– Selecionar o iésimo elemento de uma lista: 
(!!) :: [a] → Int → a 
– Verificar se um valor é um elemento de da lista: 
elem :: Eq a => a → [a] → Bool
125 
Haskell 
Capítulo 7 – Funções de Alta Ordem (Funções de 
Ordem Superior)
126 
Introdução 
● Uma função é chamada de alta ordem se ela toma uma 
função como argumento ou retorna uma função como 
resultado. 
twice :: (a → a) → a → a 
twice f x = f (f x) 
twice é uma função de alta ordem porque toma uma 
twice é uma função de alta ordem porque toma uma 
função como seu primeiro argumento 
função como seu primeiro argumento
127 
Porque são tão úteis? 
● Idiomas comuns de programação podem ser 
codificados como funções dentro própria linguagem. 
● Linguagens de domínio específico podem ser definidas 
como coleções de funções de alta ordem. 
● Propriedades algébricas de funções de alta ordem 
podem ser usadas para raciocinar sobre programas.
128 
A função map 
● A função de alta ordem da biblioteca chamada map aplica 
uma função para cada elemento de uma lista. 
map :: (a → b) → [a] → [b] 
● Por exemplo: 
> map (+1) [1,3,5,7] 
[2,4,6,8]
129 
A função map (2) 
● A função map pode ser definida em uma maneira 
particularmente simples usando compreensão de lista. 
map f xs = [f x | x ← xs] 
Alternativamente, para provar, a função map pode ser 
definida utilizando recursão: 
map f [] = [] 
map f (x:xs) = f x : map f xs
130 
A função filter 
● A função de alta ordem filter seleciona todos os 
elementos de uma lista que satisfazem um predicado. 
filter :: (a → Bool) → [a] → [a] 
● Por exemplo: 
> filter even [1..10] 
[2,4,6,8,10]
131 
A função filter (2) 
● Filter pode ser definida utilizando compreensão de lista. 
filter p xs = [x | x ← xs, p x] 
Alternativamente, pode ser definida utilizando recursão: 
filter p [] = [] 
filter p (x:xs) 
| p x = x : filter p xs 
| otherwise = filter p xs
132 
A função foldr 
● Várias funções em listas podem ser definidas utilizando o 
seguinte padrão simples: 
f [] = v 
f (x:xs) = x ⊕ f xs 
f mapeia um lista vazia para algum valor v, e 
qualquer outra lista não vazia para alguma uma 
função ⊕ aplicada na cabeça e f na calda 
f mapeia um lista vazia para algum valor v, e 
qualquer outra lista não vazia para alguma uma 
função ⊕ aplicada na cabeça e f na calda
133 
A função foldr (2) - Exemplo 
sum [] = 0 
sum (x:xs) = x + sum xs v = 0 
v = 0 
⊕ = + 
⊕ = + 
product [] = 1 
product (x:xs) = x * product xs 
v = 1 
⊕ = * 
v = 1 
⊕ = * 
and [] = True 
and (x:xs) = x && and xs 
v = True 
⊕ = && 
v = True 
⊕ = &&
134 
A função foldr (3) 
● A função de alta ordem foldr (fold right) encapsula este 
padrão de recursão simples, juntamente com a função ⊕ 
e o valor v como argumentos. 
sum = foldr (+) 0 
product = foldr (*) 1 
or = foldr (||) False 
and = foldr (&&) True
135 
A função foldr (4) 
● foldr pode ser definida usando recursão: 
foldr :: (a -> b -> b) -> b -> [a] -> b 
foldr f v [] = v 
foldr f v (x:xs) = f x (foldr f v xs) 
● No entanto, é melhor pensar em foldr de forma não 
recursiva, simultaneamente substituindo cada (:) em uma 
lista para um função dada, e [] para um valor dado.
136 
A função foldr (5) 
sum [1,2,3] 
= 
foldr (+) 0 [1,2,3] 
= 
foldr (+) 0 (1:(2:(3:[]))) 
= 
1+(2+(3+0)) 
= 
6 
Substitua cada (:) 
por (+) e [] por 0 
Substitua cada (:) 
por (+) e [] por 0
137 
A função foldr (6) 
product [1,2,3] 
= 
foldr (*) 1 [1,2,3] 
= 
foldr (*) 1 (1:(2:(3:[]))) 
= 
1*(2*(3*1)) 
= 
6 
Substitua cada (:) 
por (*) e [] por 1 
Substitua cada (:) 
por (*) e [] por 1
138 
A função foldr (7) 
● Mesmo foldr encapsulando um padrão de recursão 
simples, ela pode ser usada para definir muitas outras 
funções do que se possa esperar. 
● Relembrando a função length: 
length :: [a] -> Int 
length [] = 0 
length (_:xs) = 1 + length xs
Substitua cada (:) 
por λ_ n → 1+n e 
139 
A função foldr (8) 
length [1,2,3] 
= 
length (1:(2:(3:[]))) 
= 
1+(1+(1+0)) 
= 
3 
Substitua cada (:) 
por λ_ n → 1+n e 
[] por 0 
[] por 0 
length = foldr (_ n -> 1+n) 0
Reverse [] = [] 
reverse (x:xs) = reverse xs ++ [x] 
Substitua cada (:) 
por λx xs → xs ++ 
140 
A função foldr (9) 
reverse [1,2,3] 
= 
reverse (1:(2:(3:[]))) 
= 
(([] ++ [3]) ++ [2]) ++ [1] 
= 
[3,2,1] 
Substitua cada (:) 
por λx xs → xs ++ 
[x] e [] por [] 
[x] e [] por [] 
● Agora relembrando a função reverse:
Substitua cada (:) 
por (:) [] por ys 
141 
A função foldr (10) 
● Portanto, nós temos: 
(++ ys) = foldr (:) ys Substitua cada (:) 
por (:) [] por ys 
reverse = 
foldr (x xs -> xs ++ [x]) [] 
● Finalmente, nota-se que a função de concatenação (++) 
tem uma definição particularmente compacta utilizando 
foldr:
142 
Por que foldr é útil? 
● Algumas funções recursivas em listas, como sum, são 
mais simples de definir usando foldr; 
● Propriedades de funções definidas usando foldr podem 
ser provadas usando propriedades algébricas de foldr, 
como fusão e a regra da banana split; 
● Otimizações avançadas de programa podem ser simples 
se foldr é usado ao invés de recursão explícita.
(.) :: (b -> c) -> (a -> b) -> (a -> c) 
f . g = x -> f (g x) 
143 
Outras funções de biblioteca 
● A função de biblioteca (.) retorna a composição de duas 
funções como um única função. 
● Por exemplo: 
odd :: Int -> Bool 
odd = not . even
144 
Outras funções de biblioteca (2) 
● A função de biblioteca all decide se todos os elementos de 
uma lista satisfazem um dado predicado. 
all :: (a -> Bool) -> [a] -> Bool 
all p xs = and [p x | x <- xs] 
● Por exemplo: 
> all even [2,4,6,8,10] 
True
145 
Outras funções de biblioteca (3) 
● Similarmente, a função de biblioteca any decide se pelo 
menos um elemento de uma lista satisfaz um dado 
predicado. 
any :: (a -> Bool) -> [a] -> Bool 
any p xs = or [p x | x <- xs] 
● Por exemplo: 
> any isSpace "abc def" 
True
takeWhile :: (a -> Bool) -> [a] -> [a] 
takeWhile p [] = [] 
takeWhile p (x:xs) 
146 
Outras funções de biblioteca (4) 
● A função de biblioteca takeWhile seleciona elementos de 
uma lista enquanto um predicado for verdadeiro. 
| p x = x : takeWhile p xs 
| otherwise = [] 
● Por exemplo: 
> takeWhile isAlpha "abc def" 
"abc"
dropWhile :: (a -> Bool) -> [a] -> [a] 
dropWhile p [] = [] 
dropWhile p (x:xs) 
147 
Outras funções de biblioteca (5) 
● A função de biblioteca takeWhile seleciona elementos de 
uma lista enquanto um predicado for verdadeiro. 
| p x = dropWhile p xs 
| otherwise = x:xs 
● Por exemplo: 
> dropWhile isSpace " abc" 
"abc"
148 
Exercícios 
● Expresse a compreensão [f x | x ← xs, p x] utilizando as 
funções map e filter. 
● Redefina map f e filter p usando foldr.
149 
Analisadores Funcionais 
Monads
150 
O que é um analisador (parser)? 
● Um analisador é um programa que analisa um trecho de 
texto para determinar sua estrutura sintática. 
2*3+4 significa 
+ 
* 4 
2 3
151 
Para que são utilizados? 
● Praticamente todos programas do cotidiano usam alguma 
forma análise para pré-processar suas entradas: 
Hugs 
Unix 
Browser 
analisa 
Programas Haskell 
Scripts de shell 
Documentos HTML
152 
O tipo Parser 
● Em uma linguagem funcional como Haskell, analisadores 
podem ser vistos naturalmente como funções: 
type Parser = String -> Tree 
Um analisador é uma função que toma uma string e 
Um analisador é uma função que toma uma string e 
retorna alguma forma de árvore 
retorna alguma forma de árvore
153 
O tipo Parser (2) 
● No entanto, um analisador pode não requerer toda sua 
string de entrada, sendo assim também é retornada a 
entrada não utilizada. 
type Parser = String -> (Tree,String) 
● Uma string pode ser analisada de várias maneiras, 
incluindo nenhuma, então generaliza-se para uma lista de 
resultados: 
type Parser = String -> [(Tree,String)]
154 
O tipo Parser (3) 
● Finalmente, um analisador nem sempre pode produzir 
uma árvore, então generaliza-se para uma valor de 
qualquer tipo: 
type Parser = String -> [(a,String)] 
Nota: 
Para simplificar, esta sendo considerado somente 
analisadores que ou falham e retornam um lista vazia 
de resultados, ou têm sucesso e retornam uma lista 
singleton (apenas um valor). 
Nota: 
Para simplificar, esta sendo considerado somente 
analisadores que ou falham e retornam um lista vazia 
de resultados, ou têm sucesso e retornam uma lista 
singleton (apenas um valor).
155 
Analisadores básicos 
● O analisador item falha se a entrada é vazia, e consome o 
primeiro caractere caso contrário: 
item :: Parser Char 
item = inp -> case inp of 
[] -> [] 
(x:xs) -> [(x,xs)]
156 
Analisadores básicos (2) 
● O analisador failure sempre falha: 
failure :: Parser a 
failure = inp -> [] 
● O analisador return sempre tem sucesso, retornando o 
valor v sem consumir nenhuma entrada: 
return :: a -> Parser a 
return v = inp -> [(v,inp)]
157 
Analisadores básicos (2) 
● O analisador p +++ q se comporta como o analisador p se 
tiver sucesso, e como o analisador q caso contrário: 
(+++) :: Parser a -> Parser a -> Parser a 
p +++ q = inp -> case p inp of 
[] -> parse q inp 
[(v,out)] -> [(v,out)] 
● A função parse aplica um analisador a uma string: 
parse :: Parser a -> String -> [(a,String)] 
parse p inp = p inp
158 
Exemplos 
● O comportamento dos cinco analisadores primitivos 
podem ser ilustrados com exemplos simples: 
% hugs parse.hs 
> parse item “” 
[] 
> parse item “abc” 
[('a',”bc”)]
159 
Exemplos (2) 
> parse failure "abc" 
[] 
> parse (return 1) "abc" 
[(1,"abc")] 
> parse (item +++ return 'd') "abc" 
[('a',"bc")] 
> parse (failure +++ return 'd') "abc" 
[('d',"abc")]
160 
Nota 
● O arquivo de biblioteca Parsing está disponível na web na 
home page de Programming in Haskell. 
● O tipo Parser é um monad, uma estrutura matemática que 
ser provou útil na modelagem de vários tipos de 
computações diferentes.
161 
Sequenciamento 
● Uma sequência de analisadores pode ser combinada um 
um único analisador composto utilizando a palavra-chave 
do. 
● Por exemplo: 
p :: Parser (Char, Char) 
p = do x <- item 
item 
y <- item 
return (x,y)
162 
Sequenciamento (2) 
● Se qualquer analisador em uma sequência de 
analisadores falhar, então a sequência interia falhará. Por 
exemplo: 
> parse p "abcdef" 
[(('a','c'), "def")] 
> parse p "ab" 
[] 
● A notação do não é especificada no tipo Parser, mas pode 
ser utilizada com qualquer tipo monadico.
163 
Primitivas derivadas 
● Analisando um caractere que satisfaz um predicado: 
sat :: (Char -> Bool) -> Parser Char 
sat p = do x <- item 
if p x then 
return x 
else 
failure
164 
Primitivas derivadas (2) 
● Analisando um dígito e caracteres específicos: 
digit :: Parser Char 
digit = sat isDigit 
char :: Char -> Parser Char 
char x = sat (x ==) 
● Aplicando um analisador zero ou mais vezes: 
many :: Parser a -> Parser [a] 
many p = many1 p +++ return []
165 
Primitivas derivadas (3) 
● Aplicando um analisador uma ou mais vezes: 
many1 :: Parser a -> Parser [] 
many1 p = do v <- p 
vs <- many p 
return (v:vs) 
● Analisando um string de caracteres específica: 
string :: String -> Parser String 
string [] = return [] 
string (x:xs) = do char x 
string xs 
return (x:xs)
166 
Exemplo 
● Agora é possível definir um analisador que consome um 
lista de um ou mais dígitos de uma string: 
p :: Parser String 
p = do char '[' 
d <- digit 
ds <- many (do char ',' 
digit) 
char ']' 
return (d:ds)
167 
Exemplo (2) 
● Agora é possível definir um analisador que consome um 
lista de um ou mais dígitos de uma string: 
> parse p "[1,2,3,4]" 
[("1234","")] 
> parse p "[1,2,3,4" 
[] 
Nota: 
Bibliotecas de análise mais sofisticadas podem 
indicar e/ou recuperar-se de erros na string de 
entrada. 
Nota: 
Bibliotecas de análise mais sofisticadas podem 
indicar e/ou recuperar-se de erros na string de 
entrada.
168 
Expressões aritméticas 
● Considerando uma simples forma de expressões 
construídas a partir de dígitos únicos usando operações 
de adição + e multiplicação *, juntas com parênteses. 
● Assumindo também que: 
– * e + associados a direita; 
– * tem prioridade maior do que +.
169 
Expressões aritméticas (2) 
● Formalmente, a sintaxe de tais expressões é definida pela 
seguinte gramática livre de contexto: 
exp → term '+' expr | term 
term → factor '*' term | factor 
factor → digit | '(' expr ')' 
digit → '0' | '1' | … | '9'
170 
Expressões aritméticas (2) 
● No entanto, por razões de eficiência, é importante fatorizar 
as regras para expr e term. 
exp → term ('+' expr | ε) 
term → term ('*' term | ε) 
Nota: 
O símbolo ε denota uma string vazia. 
Nota: 
O símbolo ε denota uma string vazia.
171 
Expressões aritméticas (2) 
● Agora é fácil traduzir a gramática em um analisador que 
avalia expressões, simplesmente reescrevendo as regras 
da gramática utilizando as primitivas de análise. 
expr :: Parser Int 
expr = do t <- term 
do char '+' 
e <- expr 
return (t + e) 
+++ return t
172 
Expressões aritméticas (3) 
term :: Parser Int 
term = do f <- factor 
do char '*' 
t <- term 
return (f * t) 
+++ return f 
factor :: Parser Int 
factor = do d <- digit 
return (digitToInt d) 
+++ do char '(' 
e <- expr 
char ')' 
return e
173 
Expressões aritméticas (4) 
● Finalmente, definido: 
eval :: String -> Int 
eval xs = fst (head (parse expr xs)) 
● E testando alguns exemplos: 
> eval "2*3+4" 
10 
> eval "2*(3+4)" 
14
174 
Programas Interativos
175 
Introdução 
● Até agora vimos como Haskell pode ser usado para 
escrever programas em lote que tomam todas as suas 
entradas no início e retornam todas as suas saídas no 
final. 
programa 
em lote 
programa 
em lote 
entradas saídas
176 
teclado 
programa 
interativo 
entradas saídas 
tela 
Introdução (2) 
● No entanto, também gostaríamos de usar Haskell para 
escrever programas interativos que leem a partir de um 
teclado e escrevem na tela, enquanto estiverem em 
execução.
177 
O problema 
● Programas em Haskell são funções matemáticas puras: 
– Programas em Haskell não têm efeitos colaterais. 
● No entanto, ler de um teclado e escrever em uma tela são 
efeitos colaterais: 
– Programas interativos tem efeitos colaterais.
178 
A solução 
● Programas interativos podem ser escritos em Haskell 
usando tipos para distinguir expressões puras de ações 
impuras que podem envolver efeitos colaterais. 
IIOO aa 
Os tipos de ações que 
retornam um valor do tipo a. 
Os tipos de ações que 
retornam um valor do tipo a.
179 
Por exemplo 
IIOO CChhaarr 
IIOO (()) 
O tipo de ações que 
retornam um caractere. 
O tipo de ações que 
retornam um caractere. 
O tipo de ações puramente 
com efeitos colaterais que 
não retornam nenhum 
O tipo de ações puramente 
com efeitos colaterais que 
não retornam nenhum 
valor. 
valor. 
Nota: 
() é um tipo de tupla sem componentes. 
Nota: 
() é um tipo de tupla sem componentes.
– A ação getChar lê um caractere do teclado, ecoa na 
tela, e retorna o caractere como seu valor de resultado. 
180 
Ações básicas 
● A biblioteca padrão fornece várias ações incluindo as 
seguintes ações primitivas: 
getChar :: IO Char
181 
Ações básicas (2) 
● A ação putChar c escreve o caractere c na tela, e não 
retorna nenhum valor como resultado: 
putChar :: Char -> IO () 
● A ação return v simplesmente retorna o valor v, sem 
realizar nenhuma interação: 
return :: a -> IO a
182 
Sequenciamento 
● Uma sequência de ações podem ser combinadas como 
uma única ação composta usando a palavra do. 
a :: IO (Char,Char) 
a = do x <- getChar 
getChar 
Y <- getChar 
return (x,y) 
● Por exemplo:
183 
getLine :: IO String 
getLine = do x <- getChar 
if x == 'n' then 
return [] 
else 
do xs <- getLine 
return (x:xs) 
Primitivas derivadas 
● Lendo uma string a partir do teclado:
184 
putStr :: String -> IO () 
putStr [] = return () 
putStr (x:xs) = do putChar x 
putStr xs 
putStrLn :: String -> IO () 
putStrLn xs = do putStr xs 
putChar 'n' 
Primitivas derivadas(2) 
● Escrevendo uma string na tela: 
● Escrevendo uma string e movendo para uma nova linha:
185 
strlen :: IO () 
strlen = do putStr "Enter a string: " 
Xs <- getLine 
putStr "The string has " 
putStr (show (length xs)) 
putStrLn " characters" 
Exemplo 
● Agora é possível definir uma ação que espera uma string 
ser entrada e mostra seu comprimento:
186 
Exemplo (2) 
> strlen 
Enter a string: abcde 
The string has 5 characters 
Nota: 
Avaliar uma ação executa seus efeitos colaterais, 
com seu valor final de resultado sendo descartado. 
Nota: 
Avaliar uma ação executa seus efeitos colaterais, 
com seu valor final de resultado sendo descartado.
187 
Jogo da forca 
● Considere a seguinte versão do jogo da forca: 
– Um jogador digita uma palavra secretamente; 
– O outro jogador tenta deduzir a palavra, entrando uma 
sequência de “chutes”; 
– Para cada “chute”, o computador indica quais letras da 
palavra secreta ocorrem no “chute”; 
– O jogo acaba quando o “chute” estiver correto.
188 
Jogo da forca (2) 
● Foi adotado a abordagem top-down para implementar o 
jogo da forca em Haskell, iniciando como se segue: 
hangman :: IO () 
hangman = 
do putStrLn "Think of a word: " 
Word <- sgetLine 
putStrLn "Try to guess it:" 
guess word
189 
sgetLine :: IO String 
sgetLine = do x <- getCh 
if x == 'n' then 
do putChar x 
return [] 
else 
do putChar '-' 
Xs <- sgetLine 
return (x:xs) 
Jogo da forca (3) 
● A ação sgetLine lê um linha de texto do teclado, ecoando 
cada caractere como um traço -:
190 
import System.IO 
getCh :: IO Char 
getCh = do hSetEcho stdin False 
C <- getChar 
hSetEcho stdin True 
return c 
Jogo da forca (4) 
● A ação getCh lê um único caractere do teclado, sem ecoar 
para a tela:
191 
guess :: String -> IO () 
guess word = 
do putStr "> " 
Xs <- getLine 
if xs == word then 
putStrLn "You got it!" 
else 
do putStrLn (diff word xs) 
guess word 
Jogo da forca (5) 
● A função guess é o loop principal, que requisita e 
processa os “chutes” até o jogo terminar:
Jogo da forca (6) 
● A função diff indica quais caracteres de uma string 
ocorrem na segunda string: 
[if elem x ys then x else '-' | x <- xs] 
192 
diff :: String -> String -> String 
diff xs ys = 
● Por exemplo: 
> diff "haskell" "pascal" 
"-as--ll"
Dica: 
Represente o tabuleiro como 
uma lista de cinco inteiros que 
representam o número de 
asteriscos remanescentes em 
cada linha. Por exemplo, o 
tabuleiro inicial é: [5,4,3,2,1]. 
193 
1: * * * * * 
2: * * * * 
3: * * * 
4: * * 
5: * 
Exercício 
● Implemente o jogo nim em Haskell 
– Regras: 
● O tabuleiro é composto de 5 linhas 
de asteriscos; 
● Dois jogadores revesam a 
remoção de um ou mais asteriscos 
do fim de uma única linha; 
● O ganhador é o jogador que 
remover o último asterisco ou 
asteriscos do tabuleiro. Dica: 
Represente o tabuleiro como 
uma lista de cinco inteiros que 
representam o número de 
asteriscos remanescentes em 
cada linha. Por exemplo, o 
tabuleiro inicial é: [5,4,3,2,1].
Capítulo 10 – Declarando tipos e classes
Declarações de tipo 
● Em Haskell, um novo nome para um tipo existente pode 
ser definido usando uma declaração de tipo. 
type String = [Char] 
String String éé uumm ssiinnôônniimmoo ddee ttiippoo [[CChhaarr]]..
Declarações de tipo (2) 
● Declarações de tipo podem ser usadas para tornar outros 
tipos mais simples de ler. Por exemplo, dado 
type Pos = (Int,Int) 
● Pode-se definir: 
origin :: Pos 
origin = (0,0) 
left :: Pos -> Pos 
left (x,y) = (x-1,y)
Declarações de tipo (3) 
● Como definições de funções, declarações de tipo também 
podem conter parâmetros. Por exemplo, dado 
type Pair a = (a,a) 
● Pode-se definir: 
mult :: Pair Int -> Int 
mult (m,n) = m*n 
copy :: a -> Pair a 
copy x = (x,x)
Declarações de tipo (3) 
● Declarações de tipo podem ser aninhadas: 
type Pos = (Int,Int) 
type Trans = Pos -> 
Pos 
● No entando, não podem ser recursivas: 
type Tree = (Int,[Tree])
199 
Declarações de dados 
● Um tipo completamente novo pode ser definido 
especificando seus valores uma uma declaração de 
dados. 
data Bool = False | True 
Bool é um novo tipo, com dois 
novos valores False e True. 
Bool é um novo tipo, com dois 
novos valores False e True.
Declarações de dados (2) 
● Nota: 
– Os dois valores False e True podem ser chamados de 
construtores do tipo Bool; 
– Nomes de tipos e construtores devem iniciar com letra 
maiúscula; 
– Declarações de dados são similares à gramáticas livres 
de contexto. O primeiro especifica os valores do tipo, e 
o último as sentenças da linguagem.
Declarações de dados (3) 
● Valores de novos tipos podem ser usados da mesma 
forma dos tipos nativos. Por exemplo, dado 
data Answer = Yes | No | Unknown 
● Pode-se definir: 
answers :: [Answer] 
answers = [Yes,No,Unknown] 
flip :: Answer -> Answer 
flip Yes = No 
flip No = Yes 
flip Unknown = Unknown
Declarações de dados (4) 
● Os construtores um uma declaração de dados também 
podem possuir parâmetros. Por exemplo, dado 
data Shape = Circle Float 
● Pode-se definir: 
| Rect Float Float 
square :: Float -> Shape 
square n = Rect n n 
area :: Shape -> Float 
area (Circle r) = pi * r^2 
area (Rect x y) = x * y
Declarações de dados (5) 
● Nota: 
– Shape possui valores da forma Circle r onde r é float, e 
Rect x y onde x e y são floats. 
– Circle e Rect podem ser vistos como funções que 
constroem valores do tipo Shape: 
Circle :: Float -> Shape 
Rect :: Float -> Float -> Shape
Declarações de dados (6) 
● Sem surpresas, as próprias declarações de dados podem 
conter parâmetros. Por exemplo, dado 
data Maybe a = Nothing | Just a 
● Pode-se definir: 
safediv :: Int -> Int -> Maybe Int 
safediv _ 0 = Nothing 
safediv m n = Just (m `div` n) 
safehead :: [a] -> Maybe a 
safehead [] = Nothing 
safehead xs = Just (head xs)
205 
Referências 
● Meijer, Erik. C9 Lectures: Functional Programming 
Fundamentals. Disponível em: 
<http://channel9.msdn.com/Series/C9-Lectures-Erik- 
Meijer-Functional-Programming-Fundamentals/Lecture- 
Series-Erik-Meijer-Functional-Programming- 
Fundamentals-Chapter-1>

Mais conteúdo relacionado

Mais procurados

Introdução a Gerência de Configuração de Software
Introdução a Gerência de Configuração de SoftwareIntrodução a Gerência de Configuração de Software
Introdução a Gerência de Configuração de SoftwareCamilo Almendra
 
Estrutura de Dados - Aula 01
Estrutura de Dados - Aula 01Estrutura de Dados - Aula 01
Estrutura de Dados - Aula 01thomasdacosta
 
Redes de Computadores - Aula 01
Redes de Computadores - Aula 01Redes de Computadores - Aula 01
Redes de Computadores - Aula 01thomasdacosta
 
Lógica de programação { para iniciantes }
Lógica de programação { para iniciantes }Lógica de programação { para iniciantes }
Lógica de programação { para iniciantes }Mariana Camargo
 
Aula 10 - Exclusão Mútua e Região Crítica
Aula 10 - Exclusão Mútua e Região CríticaAula 10 - Exclusão Mútua e Região Crítica
Aula 10 - Exclusão Mútua e Região Críticacamila_seixas
 
Introdução ao Word
Introdução ao WordIntrodução ao Word
Introdução ao WordArtur Coelho
 
Cálculos de balanceamento pao
Cálculos de balanceamento paoCálculos de balanceamento pao
Cálculos de balanceamento paoJose Boulos
 
Aula Lógica de Programação - cap1
Aula Lógica de Programação - cap1 Aula Lógica de Programação - cap1
Aula Lógica de Programação - cap1 Cloves da Rocha
 
Curso de HTML5 - Aula 01
Curso de HTML5 - Aula 01   Curso de HTML5 - Aula 01
Curso de HTML5 - Aula 01 Léo Dias
 
Classificação das redes quanto a abrangência geográfica
Classificação das redes quanto a abrangência geográficaClassificação das redes quanto a abrangência geográfica
Classificação das redes quanto a abrangência geográficaFábio Pires
 
IMEI Módulo 8 (Curso profissional de Gestão de Equipamentos Informáticos)
IMEI Módulo 8 (Curso profissional de Gestão de Equipamentos Informáticos)IMEI Módulo 8 (Curso profissional de Gestão de Equipamentos Informáticos)
IMEI Módulo 8 (Curso profissional de Gestão de Equipamentos Informáticos)Luis Ferreira
 
Curso Linguagem de Programação I - PHP Básico
Curso Linguagem de Programação I - PHP BásicoCurso Linguagem de Programação I - PHP Básico
Curso Linguagem de Programação I - PHP BásicoNorton Guimarães
 
Exemplo e caso prático do uso de base de dados
Exemplo e caso prático do uso de base de dadosExemplo e caso prático do uso de base de dados
Exemplo e caso prático do uso de base de dadosLuis Borges Gouveia
 
Aula 1 - Introdução a POO
Aula 1 -  Introdução a POOAula 1 -  Introdução a POO
Aula 1 - Introdução a POODaniel Brandão
 

Mais procurados (20)

Introdução a Gerência de Configuração de Software
Introdução a Gerência de Configuração de SoftwareIntrodução a Gerência de Configuração de Software
Introdução a Gerência de Configuração de Software
 
Estrutura de Dados - Aula 01
Estrutura de Dados - Aula 01Estrutura de Dados - Aula 01
Estrutura de Dados - Aula 01
 
Redes de Computadores - Aula 01
Redes de Computadores - Aula 01Redes de Computadores - Aula 01
Redes de Computadores - Aula 01
 
Lógica de programação { para iniciantes }
Lógica de programação { para iniciantes }Lógica de programação { para iniciantes }
Lógica de programação { para iniciantes }
 
CON08 - VLAN.pdf
CON08 - VLAN.pdfCON08 - VLAN.pdf
CON08 - VLAN.pdf
 
Aula 10 - Exclusão Mútua e Região Crítica
Aula 10 - Exclusão Mútua e Região CríticaAula 10 - Exclusão Mútua e Região Crítica
Aula 10 - Exclusão Mútua e Região Crítica
 
Introdução ao Word
Introdução ao WordIntrodução ao Word
Introdução ao Word
 
SI - Comunicação
SI - ComunicaçãoSI - Comunicação
SI - Comunicação
 
Algoritmo 04 - Estruturas de decisão
 Algoritmo 04 - Estruturas de decisão Algoritmo 04 - Estruturas de decisão
Algoritmo 04 - Estruturas de decisão
 
Cálculos de balanceamento pao
Cálculos de balanceamento paoCálculos de balanceamento pao
Cálculos de balanceamento pao
 
Aula Lógica de Programação - cap1
Aula Lógica de Programação - cap1 Aula Lógica de Programação - cap1
Aula Lógica de Programação - cap1
 
Curso de HTML5 - Aula 01
Curso de HTML5 - Aula 01   Curso de HTML5 - Aula 01
Curso de HTML5 - Aula 01
 
Classificação das redes quanto a abrangência geográfica
Classificação das redes quanto a abrangência geográficaClassificação das redes quanto a abrangência geográfica
Classificação das redes quanto a abrangência geográfica
 
IMEI Módulo 8 (Curso profissional de Gestão de Equipamentos Informáticos)
IMEI Módulo 8 (Curso profissional de Gestão de Equipamentos Informáticos)IMEI Módulo 8 (Curso profissional de Gestão de Equipamentos Informáticos)
IMEI Módulo 8 (Curso profissional de Gestão de Equipamentos Informáticos)
 
Word Avançado
Word AvançadoWord Avançado
Word Avançado
 
Curso Linguagem de Programação I - PHP Básico
Curso Linguagem de Programação I - PHP BásicoCurso Linguagem de Programação I - PHP Básico
Curso Linguagem de Programação I - PHP Básico
 
EXCEL 2019
EXCEL 2019EXCEL 2019
EXCEL 2019
 
Exemplo e caso prático do uso de base de dados
Exemplo e caso prático do uso de base de dadosExemplo e caso prático do uso de base de dados
Exemplo e caso prático do uso de base de dados
 
Teclado e Mouse
Teclado e Mouse Teclado e Mouse
Teclado e Mouse
 
Aula 1 - Introdução a POO
Aula 1 -  Introdução a POOAula 1 -  Introdução a POO
Aula 1 - Introdução a POO
 

Destaque

Introdução ao Desenvolvimento WEB
Introdução ao Desenvolvimento WEBIntrodução ao Desenvolvimento WEB
Introdução ao Desenvolvimento WEBTony Alexander Hild
 
Portfolio Daniel Soto 2011
Portfolio Daniel Soto 2011Portfolio Daniel Soto 2011
Portfolio Daniel Soto 2011Daniel Soto
 
Palestra - design e mercado de trabalho
Palestra - design e mercado de trabalhoPalestra - design e mercado de trabalho
Palestra - design e mercado de trabalhoDaniel Soto
 
Webdesign - Gestão Profissional
Webdesign - Gestão ProfissionalWebdesign - Gestão Profissional
Webdesign - Gestão ProfissionalDaniel Soto
 
Lançamento Bahia Análise & Dados - Biodiversidade
Lançamento Bahia Análise & Dados - BiodiversidadeLançamento Bahia Análise & Dados - Biodiversidade
Lançamento Bahia Análise & Dados - BiodiversidadeDaniel Soto
 
Daniel apresentando: Victor Margolin e A Política do Artificial
Daniel apresentando: Victor Margolin e A Política do ArtificialDaniel apresentando: Victor Margolin e A Política do Artificial
Daniel apresentando: Victor Margolin e A Política do ArtificialDaniel Soto
 
CEAD 2013 - Oficina 1: Ferramentas colaborativas e de comunicação WEB
CEAD 2013 - Oficina 1: Ferramentas colaborativas e de comunicação WEBCEAD 2013 - Oficina 1: Ferramentas colaborativas e de comunicação WEB
CEAD 2013 - Oficina 1: Ferramentas colaborativas e de comunicação WEBTony Alexander Hild
 
Circuitos Mux e Demux
Circuitos Mux e Demux Circuitos Mux e Demux
Circuitos Mux e Demux Joseci Silva
 
Design Webdesign
Design WebdesignDesign Webdesign
Design WebdesignDaniel Soto
 
Computação Gráfica - Introdução ao OpenGL
Computação Gráfica - Introdução ao OpenGLComputação Gráfica - Introdução ao OpenGL
Computação Gráfica - Introdução ao OpenGLTony Alexander Hild
 
Paradigma Funcional - Caso de Estudo Haskell
Paradigma Funcional - Caso de Estudo HaskellParadigma Funcional - Caso de Estudo Haskell
Paradigma Funcional - Caso de Estudo HaskellSérgio Souza Costa
 
Simplificação de expressões Booleanas utilizando mapas de Karnaugh
Simplificação de expressões Booleanas utilizando mapas de KarnaughSimplificação de expressões Booleanas utilizando mapas de Karnaugh
Simplificação de expressões Booleanas utilizando mapas de KarnaughTony Alexander Hild
 
Computação Gráfica - Percepção Tridimensional
Computação Gráfica - Percepção TridimensionalComputação Gráfica - Percepção Tridimensional
Computação Gráfica - Percepção TridimensionalTony Alexander Hild
 
Computação grafica
Computação graficaComputação grafica
Computação graficaLucas Castro
 

Destaque (20)

Circuitos combinacionais
Circuitos combinacionaisCircuitos combinacionais
Circuitos combinacionais
 
Introdução ao Desenvolvimento WEB
Introdução ao Desenvolvimento WEBIntrodução ao Desenvolvimento WEB
Introdução ao Desenvolvimento WEB
 
Circuitos Digitais
Circuitos DigitaisCircuitos Digitais
Circuitos Digitais
 
Paradigma Orientado a Objeto
Paradigma Orientado a ObjetoParadigma Orientado a Objeto
Paradigma Orientado a Objeto
 
Portfolio Daniel Soto 2011
Portfolio Daniel Soto 2011Portfolio Daniel Soto 2011
Portfolio Daniel Soto 2011
 
Palestra - design e mercado de trabalho
Palestra - design e mercado de trabalhoPalestra - design e mercado de trabalho
Palestra - design e mercado de trabalho
 
Webdesign - Gestão Profissional
Webdesign - Gestão ProfissionalWebdesign - Gestão Profissional
Webdesign - Gestão Profissional
 
Lançamento Bahia Análise & Dados - Biodiversidade
Lançamento Bahia Análise & Dados - BiodiversidadeLançamento Bahia Análise & Dados - Biodiversidade
Lançamento Bahia Análise & Dados - Biodiversidade
 
Daniel apresentando: Victor Margolin e A Política do Artificial
Daniel apresentando: Victor Margolin e A Política do ArtificialDaniel apresentando: Victor Margolin e A Política do Artificial
Daniel apresentando: Victor Margolin e A Política do Artificial
 
CEAD 2013 - Oficina 1: Ferramentas colaborativas e de comunicação WEB
CEAD 2013 - Oficina 1: Ferramentas colaborativas e de comunicação WEBCEAD 2013 - Oficina 1: Ferramentas colaborativas e de comunicação WEB
CEAD 2013 - Oficina 1: Ferramentas colaborativas e de comunicação WEB
 
Árvore do site
Árvore do siteÁrvore do site
Árvore do site
 
Circuitos Mux e Demux
Circuitos Mux e Demux Circuitos Mux e Demux
Circuitos Mux e Demux
 
Design Webdesign
Design WebdesignDesign Webdesign
Design Webdesign
 
Computação Gráfica - Introdução ao OpenGL
Computação Gráfica - Introdução ao OpenGLComputação Gráfica - Introdução ao OpenGL
Computação Gráfica - Introdução ao OpenGL
 
Paradigma Funcional - Caso de Estudo Haskell
Paradigma Funcional - Caso de Estudo HaskellParadigma Funcional - Caso de Estudo Haskell
Paradigma Funcional - Caso de Estudo Haskell
 
Simplificação de expressões Booleanas utilizando mapas de Karnaugh
Simplificação de expressões Booleanas utilizando mapas de KarnaughSimplificação de expressões Booleanas utilizando mapas de Karnaugh
Simplificação de expressões Booleanas utilizando mapas de Karnaugh
 
Computação Gráfica - Percepção Tridimensional
Computação Gráfica - Percepção TridimensionalComputação Gráfica - Percepção Tridimensional
Computação Gráfica - Percepção Tridimensional
 
Circuitos sequenciais
Circuitos sequenciaisCircuitos sequenciais
Circuitos sequenciais
 
Computação grafica
Computação graficaComputação grafica
Computação grafica
 
Circuitos Integrados Digitais
Circuitos Integrados DigitaisCircuitos Integrados Digitais
Circuitos Integrados Digitais
 

Semelhante a Paradigma Funcional - Introdução ao paradigma funcional e linguagens funcionais

Lógica de programação pascal
Lógica de programação   pascalLógica de programação   pascal
Lógica de programação pascalJocelma Rios
 
Apostila C++ Básico - UNIVERSIDADE ESTADUAL PAULISTA “JÚLIO DE MESQUITA FILHO”
Apostila C++ Básico - UNIVERSIDADE ESTADUAL PAULISTA “JÚLIO DE MESQUITA FILHO”Apostila C++ Básico - UNIVERSIDADE ESTADUAL PAULISTA “JÚLIO DE MESQUITA FILHO”
Apostila C++ Básico - UNIVERSIDADE ESTADUAL PAULISTA “JÚLIO DE MESQUITA FILHO”Kratos879
 
Introdução a linguagem c karen lowhany
Introdução a linguagem c   karen lowhanyIntrodução a linguagem c   karen lowhany
Introdução a linguagem c karen lowhanyKaren Costa
 
Algoritmos computacionais
Algoritmos computacionaisAlgoritmos computacionais
Algoritmos computacionaisDérick Platini
 
Sistemas operacionais de rede exercicio de sala-shellscript
Sistemas operacionais de rede exercicio de sala-shellscriptSistemas operacionais de rede exercicio de sala-shellscript
Sistemas operacionais de rede exercicio de sala-shellscriptCarlos Melo
 
Linguagem C e Dev-C++ Algumas Explicações
Linguagem C e Dev-C++  Algumas ExplicaçõesLinguagem C e Dev-C++  Algumas Explicações
Linguagem C e Dev-C++ Algumas Explicaçõesnataferraz
 
Conceito de funçao e modularizaçao
Conceito de funçao e modularizaçaoConceito de funçao e modularizaçao
Conceito de funçao e modularizaçaossuserc6132d
 
C curso - notas de aula
C   curso - notas de aulaC   curso - notas de aula
C curso - notas de aulaLoAlves21
 
Linguagem de programação haskell
Linguagem de programação haskellLinguagem de programação haskell
Linguagem de programação haskellDaniel Farias
 
Apostila de-introdução-à-linguagem-c
Apostila de-introdução-à-linguagem-cApostila de-introdução-à-linguagem-c
Apostila de-introdução-à-linguagem-cMaicon Rodrigues
 
Apostila de Linguagem C
Apostila de Linguagem CApostila de Linguagem C
Apostila de Linguagem CDaniel Barão
 
mod3-programação-estruturada
mod3-programação-estruturadamod3-programação-estruturada
mod3-programação-estruturadadiogoa21
 
Tutorial Octave Matlab
Tutorial Octave MatlabTutorial Octave Matlab
Tutorial Octave Matlabblogmaxima
 

Semelhante a Paradigma Funcional - Introdução ao paradigma funcional e linguagens funcionais (20)

Haskell
HaskellHaskell
Haskell
 
Haskell
HaskellHaskell
Haskell
 
Lógica de programação pascal
Lógica de programação   pascalLógica de programação   pascal
Lógica de programação pascal
 
Apostila C++ Básico - UNIVERSIDADE ESTADUAL PAULISTA “JÚLIO DE MESQUITA FILHO”
Apostila C++ Básico - UNIVERSIDADE ESTADUAL PAULISTA “JÚLIO DE MESQUITA FILHO”Apostila C++ Básico - UNIVERSIDADE ESTADUAL PAULISTA “JÚLIO DE MESQUITA FILHO”
Apostila C++ Básico - UNIVERSIDADE ESTADUAL PAULISTA “JÚLIO DE MESQUITA FILHO”
 
Apostila c++ básico
Apostila c++ básicoApostila c++ básico
Apostila c++ básico
 
Apostila c++ básico (1)
Apostila c++ básico (1)Apostila c++ básico (1)
Apostila c++ básico (1)
 
Introdução a linguagem c karen lowhany
Introdução a linguagem c   karen lowhanyIntrodução a linguagem c   karen lowhany
Introdução a linguagem c karen lowhany
 
Algoritmos computacionais
Algoritmos computacionaisAlgoritmos computacionais
Algoritmos computacionais
 
Haskell - Introdução
Haskell - IntroduçãoHaskell - Introdução
Haskell - Introdução
 
Sistemas operacionais de rede exercicio de sala-shellscript
Sistemas operacionais de rede exercicio de sala-shellscriptSistemas operacionais de rede exercicio de sala-shellscript
Sistemas operacionais de rede exercicio de sala-shellscript
 
Linguagem C e Dev-C++ Algumas Explicações
Linguagem C e Dev-C++  Algumas ExplicaçõesLinguagem C e Dev-C++  Algumas Explicações
Linguagem C e Dev-C++ Algumas Explicações
 
Conceito de funçao e modularizaçao
Conceito de funçao e modularizaçaoConceito de funçao e modularizaçao
Conceito de funçao e modularizaçao
 
C curso - notas de aula
C   curso - notas de aulaC   curso - notas de aula
C curso - notas de aula
 
Linguagem de programação haskell
Linguagem de programação haskellLinguagem de programação haskell
Linguagem de programação haskell
 
Apostila de-introdução-à-linguagem-c
Apostila de-introdução-à-linguagem-cApostila de-introdução-à-linguagem-c
Apostila de-introdução-à-linguagem-c
 
Apostila de Linguagem C
Apostila de Linguagem CApostila de Linguagem C
Apostila de Linguagem C
 
Apostila linguagem pascal
Apostila linguagem pascalApostila linguagem pascal
Apostila linguagem pascal
 
mod3-programação-estruturada
mod3-programação-estruturadamod3-programação-estruturada
mod3-programação-estruturada
 
Tutorial Octave Matlab
Tutorial Octave MatlabTutorial Octave Matlab
Tutorial Octave Matlab
 
Pi1415 tudo
Pi1415 tudoPi1415 tudo
Pi1415 tudo
 

Mais de Tony Alexander Hild

Introdução aos Mapas de Karnaugh
Introdução aos Mapas de KarnaughIntrodução aos Mapas de Karnaugh
Introdução aos Mapas de KarnaughTony Alexander Hild
 
Introdução ao paradigma imperativo
Introdução ao paradigma imperativoIntrodução ao paradigma imperativo
Introdução ao paradigma imperativoTony Alexander Hild
 
Computação Gráfica - Transformações Geométricas no Plano e no Espaço
Computação Gráfica - Transformações Geométricas no Plano e no EspaçoComputação Gráfica - Transformações Geométricas no Plano e no Espaço
Computação Gráfica - Transformações Geométricas no Plano e no EspaçoTony Alexander Hild
 
Computação Gráfica - Artquitetura de Dispositivos Gráficos
Computação Gráfica - Artquitetura de Dispositivos GráficosComputação Gráfica - Artquitetura de Dispositivos Gráficos
Computação Gráfica - Artquitetura de Dispositivos GráficosTony Alexander Hild
 
Computação Gráfica - Informações Visuais Óculo-motoras
Computação Gráfica - Informações Visuais Óculo-motorasComputação Gráfica - Informações Visuais Óculo-motoras
Computação Gráfica - Informações Visuais Óculo-motorasTony Alexander Hild
 
Computação Gráfica - Introdução
Computação Gráfica - IntroduçãoComputação Gráfica - Introdução
Computação Gráfica - IntroduçãoTony Alexander Hild
 

Mais de Tony Alexander Hild (7)

Introdução aos Mapas de Karnaugh
Introdução aos Mapas de KarnaughIntrodução aos Mapas de Karnaugh
Introdução aos Mapas de Karnaugh
 
Introdução ao paradigma imperativo
Introdução ao paradigma imperativoIntrodução ao paradigma imperativo
Introdução ao paradigma imperativo
 
Álgebra Booleana
Álgebra BooleanaÁlgebra Booleana
Álgebra Booleana
 
Computação Gráfica - Transformações Geométricas no Plano e no Espaço
Computação Gráfica - Transformações Geométricas no Plano e no EspaçoComputação Gráfica - Transformações Geométricas no Plano e no Espaço
Computação Gráfica - Transformações Geométricas no Plano e no Espaço
 
Computação Gráfica - Artquitetura de Dispositivos Gráficos
Computação Gráfica - Artquitetura de Dispositivos GráficosComputação Gráfica - Artquitetura de Dispositivos Gráficos
Computação Gráfica - Artquitetura de Dispositivos Gráficos
 
Computação Gráfica - Informações Visuais Óculo-motoras
Computação Gráfica - Informações Visuais Óculo-motorasComputação Gráfica - Informações Visuais Óculo-motoras
Computação Gráfica - Informações Visuais Óculo-motoras
 
Computação Gráfica - Introdução
Computação Gráfica - IntroduçãoComputação Gráfica - Introdução
Computação Gráfica - Introdução
 

Último

PROJETO DE EXTENSÃO I - Radiologia Tecnologia
PROJETO DE EXTENSÃO I - Radiologia TecnologiaPROJETO DE EXTENSÃO I - Radiologia Tecnologia
PROJETO DE EXTENSÃO I - Radiologia TecnologiaHELENO FAVACHO
 
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdf
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdfPROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdf
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdfHELENO FAVACHO
 
A QUATRO MÃOS - MARILDA CASTANHA . pdf
A QUATRO MÃOS  -  MARILDA CASTANHA . pdfA QUATRO MÃOS  -  MARILDA CASTANHA . pdf
A QUATRO MÃOS - MARILDA CASTANHA . pdfAna Lemos
 
Apresentação ISBET Jovem Aprendiz e Estágio 2023.pdf
Apresentação ISBET Jovem Aprendiz e Estágio 2023.pdfApresentação ISBET Jovem Aprendiz e Estágio 2023.pdf
Apresentação ISBET Jovem Aprendiz e Estágio 2023.pdfcomercial400681
 
PROJETO DE EXTENÇÃO - GESTÃO DE RECURSOS HUMANOS.pdf
PROJETO DE EXTENÇÃO - GESTÃO DE RECURSOS HUMANOS.pdfPROJETO DE EXTENÇÃO - GESTÃO DE RECURSOS HUMANOS.pdf
PROJETO DE EXTENÇÃO - GESTÃO DE RECURSOS HUMANOS.pdfHELENO FAVACHO
 
Recomposiçao em matematica 1 ano 2024 - ESTUDANTE 1ª série.pdf
Recomposiçao em matematica 1 ano 2024 - ESTUDANTE 1ª série.pdfRecomposiçao em matematica 1 ano 2024 - ESTUDANTE 1ª série.pdf
Recomposiçao em matematica 1 ano 2024 - ESTUDANTE 1ª série.pdfFrancisco Márcio Bezerra Oliveira
 
aula de bioquímica bioquímica dos carboidratos.ppt
aula de bioquímica bioquímica dos carboidratos.pptaula de bioquímica bioquímica dos carboidratos.ppt
aula de bioquímica bioquímica dos carboidratos.pptssuser2b53fe
 
Revolução russa e mexicana. Slides explicativos e atividades
Revolução russa e mexicana. Slides explicativos e atividadesRevolução russa e mexicana. Slides explicativos e atividades
Revolução russa e mexicana. Slides explicativos e atividadesFabianeMartins35
 
COMPETÊNCIA 2 da redação do enem prodção textual professora vanessa cavalcante
COMPETÊNCIA 2 da redação do enem prodção textual professora vanessa cavalcanteCOMPETÊNCIA 2 da redação do enem prodção textual professora vanessa cavalcante
COMPETÊNCIA 2 da redação do enem prodção textual professora vanessa cavalcanteVanessaCavalcante37
 
Currículo - Ícaro Kleisson - Tutor acadêmico.pdf
Currículo - Ícaro Kleisson - Tutor acadêmico.pdfCurrículo - Ícaro Kleisson - Tutor acadêmico.pdf
Currículo - Ícaro Kleisson - Tutor acadêmico.pdfTutor de matemática Ícaro
 
Slides Lição 6, CPAD, As Nossas Armas Espirituais, 2Tr24.pptx
Slides Lição 6, CPAD, As Nossas Armas Espirituais, 2Tr24.pptxSlides Lição 6, CPAD, As Nossas Armas Espirituais, 2Tr24.pptx
Slides Lição 6, CPAD, As Nossas Armas Espirituais, 2Tr24.pptxLuizHenriquedeAlmeid6
 
Construção (C)erta - Nós Propomos! Sertã
Construção (C)erta - Nós Propomos! SertãConstrução (C)erta - Nós Propomos! Sertã
Construção (C)erta - Nós Propomos! SertãIlda Bicacro
 
Nós Propomos! " Pinhais limpos, mundo saudável"
Nós Propomos! " Pinhais limpos, mundo saudável"Nós Propomos! " Pinhais limpos, mundo saudável"
Nós Propomos! " Pinhais limpos, mundo saudável"Ilda Bicacro
 
apostila projeto de vida 2 ano ensino médio
apostila projeto de vida 2 ano ensino médioapostila projeto de vida 2 ano ensino médio
apostila projeto de vida 2 ano ensino médiorosenilrucks
 
Jogo de Rimas - Para impressão em pdf a ser usado para crianças
Jogo de Rimas - Para impressão em pdf a ser usado para criançasJogo de Rimas - Para impressão em pdf a ser usado para crianças
Jogo de Rimas - Para impressão em pdf a ser usado para criançasSocorro Machado
 
matematica aula didatica prática e tecni
matematica aula didatica prática e tecnimatematica aula didatica prática e tecni
matematica aula didatica prática e tecniCleidianeCarvalhoPer
 
PROJETO DE EXTENSÃO I - TERAPIAS INTEGRATIVAS E COMPLEMENTARES.pdf
PROJETO DE EXTENSÃO I - TERAPIAS INTEGRATIVAS E COMPLEMENTARES.pdfPROJETO DE EXTENSÃO I - TERAPIAS INTEGRATIVAS E COMPLEMENTARES.pdf
PROJETO DE EXTENSÃO I - TERAPIAS INTEGRATIVAS E COMPLEMENTARES.pdfHELENO FAVACHO
 
Projeto_de_Extensão_Agronomia_adquira_ja_(91)_98764-0830.pdf
Projeto_de_Extensão_Agronomia_adquira_ja_(91)_98764-0830.pdfProjeto_de_Extensão_Agronomia_adquira_ja_(91)_98764-0830.pdf
Projeto_de_Extensão_Agronomia_adquira_ja_(91)_98764-0830.pdfHELENO FAVACHO
 
Apresentação em Powerpoint do Bioma Catinga.pptx
Apresentação em Powerpoint do Bioma Catinga.pptxApresentação em Powerpoint do Bioma Catinga.pptx
Apresentação em Powerpoint do Bioma Catinga.pptxLusGlissonGud
 
2° ANO - ENSINO FUNDAMENTAL ENSINO RELIGIOSO
2° ANO - ENSINO FUNDAMENTAL ENSINO RELIGIOSO2° ANO - ENSINO FUNDAMENTAL ENSINO RELIGIOSO
2° ANO - ENSINO FUNDAMENTAL ENSINO RELIGIOSOLeloIurk1
 

Último (20)

PROJETO DE EXTENSÃO I - Radiologia Tecnologia
PROJETO DE EXTENSÃO I - Radiologia TecnologiaPROJETO DE EXTENSÃO I - Radiologia Tecnologia
PROJETO DE EXTENSÃO I - Radiologia Tecnologia
 
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdf
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdfPROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdf
PROJETO DE EXTENSÃO - EDUCAÇÃO FÍSICA BACHARELADO.pdf
 
A QUATRO MÃOS - MARILDA CASTANHA . pdf
A QUATRO MÃOS  -  MARILDA CASTANHA . pdfA QUATRO MÃOS  -  MARILDA CASTANHA . pdf
A QUATRO MÃOS - MARILDA CASTANHA . pdf
 
Apresentação ISBET Jovem Aprendiz e Estágio 2023.pdf
Apresentação ISBET Jovem Aprendiz e Estágio 2023.pdfApresentação ISBET Jovem Aprendiz e Estágio 2023.pdf
Apresentação ISBET Jovem Aprendiz e Estágio 2023.pdf
 
PROJETO DE EXTENÇÃO - GESTÃO DE RECURSOS HUMANOS.pdf
PROJETO DE EXTENÇÃO - GESTÃO DE RECURSOS HUMANOS.pdfPROJETO DE EXTENÇÃO - GESTÃO DE RECURSOS HUMANOS.pdf
PROJETO DE EXTENÇÃO - GESTÃO DE RECURSOS HUMANOS.pdf
 
Recomposiçao em matematica 1 ano 2024 - ESTUDANTE 1ª série.pdf
Recomposiçao em matematica 1 ano 2024 - ESTUDANTE 1ª série.pdfRecomposiçao em matematica 1 ano 2024 - ESTUDANTE 1ª série.pdf
Recomposiçao em matematica 1 ano 2024 - ESTUDANTE 1ª série.pdf
 
aula de bioquímica bioquímica dos carboidratos.ppt
aula de bioquímica bioquímica dos carboidratos.pptaula de bioquímica bioquímica dos carboidratos.ppt
aula de bioquímica bioquímica dos carboidratos.ppt
 
Revolução russa e mexicana. Slides explicativos e atividades
Revolução russa e mexicana. Slides explicativos e atividadesRevolução russa e mexicana. Slides explicativos e atividades
Revolução russa e mexicana. Slides explicativos e atividades
 
COMPETÊNCIA 2 da redação do enem prodção textual professora vanessa cavalcante
COMPETÊNCIA 2 da redação do enem prodção textual professora vanessa cavalcanteCOMPETÊNCIA 2 da redação do enem prodção textual professora vanessa cavalcante
COMPETÊNCIA 2 da redação do enem prodção textual professora vanessa cavalcante
 
Currículo - Ícaro Kleisson - Tutor acadêmico.pdf
Currículo - Ícaro Kleisson - Tutor acadêmico.pdfCurrículo - Ícaro Kleisson - Tutor acadêmico.pdf
Currículo - Ícaro Kleisson - Tutor acadêmico.pdf
 
Slides Lição 6, CPAD, As Nossas Armas Espirituais, 2Tr24.pptx
Slides Lição 6, CPAD, As Nossas Armas Espirituais, 2Tr24.pptxSlides Lição 6, CPAD, As Nossas Armas Espirituais, 2Tr24.pptx
Slides Lição 6, CPAD, As Nossas Armas Espirituais, 2Tr24.pptx
 
Construção (C)erta - Nós Propomos! Sertã
Construção (C)erta - Nós Propomos! SertãConstrução (C)erta - Nós Propomos! Sertã
Construção (C)erta - Nós Propomos! Sertã
 
Nós Propomos! " Pinhais limpos, mundo saudável"
Nós Propomos! " Pinhais limpos, mundo saudável"Nós Propomos! " Pinhais limpos, mundo saudável"
Nós Propomos! " Pinhais limpos, mundo saudável"
 
apostila projeto de vida 2 ano ensino médio
apostila projeto de vida 2 ano ensino médioapostila projeto de vida 2 ano ensino médio
apostila projeto de vida 2 ano ensino médio
 
Jogo de Rimas - Para impressão em pdf a ser usado para crianças
Jogo de Rimas - Para impressão em pdf a ser usado para criançasJogo de Rimas - Para impressão em pdf a ser usado para crianças
Jogo de Rimas - Para impressão em pdf a ser usado para crianças
 
matematica aula didatica prática e tecni
matematica aula didatica prática e tecnimatematica aula didatica prática e tecni
matematica aula didatica prática e tecni
 
PROJETO DE EXTENSÃO I - TERAPIAS INTEGRATIVAS E COMPLEMENTARES.pdf
PROJETO DE EXTENSÃO I - TERAPIAS INTEGRATIVAS E COMPLEMENTARES.pdfPROJETO DE EXTENSÃO I - TERAPIAS INTEGRATIVAS E COMPLEMENTARES.pdf
PROJETO DE EXTENSÃO I - TERAPIAS INTEGRATIVAS E COMPLEMENTARES.pdf
 
Projeto_de_Extensão_Agronomia_adquira_ja_(91)_98764-0830.pdf
Projeto_de_Extensão_Agronomia_adquira_ja_(91)_98764-0830.pdfProjeto_de_Extensão_Agronomia_adquira_ja_(91)_98764-0830.pdf
Projeto_de_Extensão_Agronomia_adquira_ja_(91)_98764-0830.pdf
 
Apresentação em Powerpoint do Bioma Catinga.pptx
Apresentação em Powerpoint do Bioma Catinga.pptxApresentação em Powerpoint do Bioma Catinga.pptx
Apresentação em Powerpoint do Bioma Catinga.pptx
 
2° ANO - ENSINO FUNDAMENTAL ENSINO RELIGIOSO
2° ANO - ENSINO FUNDAMENTAL ENSINO RELIGIOSO2° ANO - ENSINO FUNDAMENTAL ENSINO RELIGIOSO
2° ANO - ENSINO FUNDAMENTAL ENSINO RELIGIOSO
 

Paradigma Funcional - Introdução ao paradigma funcional e linguagens funcionais

  • 1. Paradigma Funcional Paradigmas de Linguagem de Programação 3 CC – Unicentro – 2014 Prof. Tony Alexander Hild
  • 2. 2 A Crise do Software ● Como diminuir o tamanho e complexidade dos software modernos? ● Como reduzir o tempo e custo desenvolvimento de software? ● Como aumentar a confiança que os software finalizados irão funcionar corretamente?
  • 3. 3 Solução para a crise ● Uma abordagem para solucionar a crise de software foi projetar novas linguagens de programação que: – Permitissem que programas fossem escritos de forma clara, concisa e com um alto nível de abstração; – Suportassem componentes de software reutilizáveis; – Encorajassem o uso de verificação formal; – Permitissem prototipagem rápida; – Fornecessem ferramentas poderosas para a solução de problemas. ● Linguagens funcionais fornecem um arcabouço particularmente elegante para abordar estas metas.
  • 4. 4 O que é uma Linguagem Funcional? ● De uma maneira geral: – Programação funcional é um estilo de programação onde o método básico de programação é a aplicação de funções em argumentos; – Uma linguagem funcional é aquela que suporta e encoraja o estilo funcional;
  • 5. 5 Exemplo ● Somando inteiros de 1 a 10 em C#: var total = 0; for (int i = 0; i < 10; i++) { total += i; } ● O método de computação é atribuição de variáveis.
  • 6. 6 Exemplo ● Somando inteiros de 1 a 10 em Haskell: sum [1..10] ● O método de computação é aplicação de função.
  • 7. 7 Histórico ● 1930: – Alonzo Church desenvolveu o cálculo lambda (cálculo-λ): ● Uma teoria de função simples mas poderosa. ● 1950: – John McCarthy desenvolve a Lisp, a primeira linguagem funcional, com algumas influências do cálculo lambda, mas mantendo as atribuições de variáveis.
  • 8. 8 Histórico ● 1960: – Peter Landin desenvolveu a linguagem ISWIM (If you see what i mean), a primeira linguagem funcional pura, fortemente baseada no cálculo lambda, sem atribuições. ● 1970: – John Backus desenvolveu FP, uma linguagem funcional que enfatiza funções de ordem superior e raciocínio sobre programas.
  • 9. 9 Histórico ● 1970: – Robin Milner e outros criaram ML, a primeira linguagem funcional moderna, qual introduziu inferência de tipos e tipos polimórficos (generics); – ML foi concebida como uma linguagem de script para realizar provas formais. ● 1970-1980: – David Turner desenvolveu uma série de linguagens funcionais preguiçosas (lazy), culminando no sistema Miranda.
  • 10. 10 Histórico ● 1987: – Um comitê internacional de pesquisadores iniciou o desenvolvimento de Haskell, uma linguagem funcional lazy padronizada; – http://www.haskell.org/h ugs/
  • 11. 11 Histórico ● 2003: – O comitê publica o relatório Haskell 98, definindo uma definição estável da linguagem; – http://www.haskell.org/o nlinereport/
  • 12. 12 Haskell - Exemplo f [] = [] f (x:xs) = f ys ++ [x] ++ f zs where ys = [ a | a <- xs, a <= x ] zs = [ b | b <- xs, b > x ] ?
  • 13. 13 Hugs ● Implementação do Haskell 98, e é o sistema Haskell mais utilizado; ● A natureza interativa do Hugs o torna ideal para os propósitos de ensino e prototipagem; ● Disponível em: http://www.haskell.org/hugs/
  • 14. 14 Iniciando o Hugs ● Em um sistema Unix, o Hugs pode ser iniciado a partir do prompt de comando simplesmente escrevendo-se: # hugs __ __ __ __ ____ ___ _________________________________________ || || || || || || ||__ Hugs 98: Based on the Haskell 98 standard ||___|| ||__|| ||__|| __|| Copyright (c) 1994-2005 ||---|| ___|| World Wide Web: http://haskell.org/hugs || || Bugs: http://hackage.haskell.org/trac/hugs || || Version: September 2006 _________________________________________ Haskell 98 mode: Restart with command line option -98 to enable extensions Type :? for help Hugs>
  • 15. 15 Iniciando o Hugs (2) ● Hugs> significa que o sistema Hugs está pronto para avaliar uma expressão; ● Por exemplo: Hugs> 2+3*4 14 Hugs> (2+3)*4 20 Hugs> sqrt (3^2 + 4^2) 5.0
  • 16. 16 O Prelude padrão ● Haskell contém uma biblioteca chamada Prelude.hs que contém um grande número de funções: – Funções numéricas: +, *; – Funções em listas.
  • 17. 17 Funções em listas ● Seleciona o primeiro elemento de uma lista: > head [1,2,3,4,5] 1 ● Remove o primeiro elemento de uma lista: > tail [1,2,3,4,5] [2,3,4,5] ● Seleciona o enésimo elemento de uma lista: > [1,2,3,4,5] !! 2 3 ● Seleciona os primeiros n elementos de uma lista: > take 3 [1,2,3,4,5] [1,2,3]
  • 18. 18 Funções em listas (2) ● Remove os primeiros n elementos de uma lista: > drop 3 [1,2,3,4,5] [4,5] ● Calcula o comprimento de uma lista: > length [1,2,3,4,5] 5 ● Calcula a soma dos elementos de uma lista: > sum [1,2,3,4,5] 15
  • 19. 19 Funções em listas (3) ● Calcula o produto dos elementos de uma lista: > product [1,2,3,4,5] 120 ● Junta duas listas: > [1,2,3] ++ [4,5] [1,2,3,4,5] ● Reverte uma lista: > reverse [1,2,3,4,5] [5,4,3,2,1]
  • 20. 20 Aplicação de funções ● Na matemática, a aplicação de uma função é denotada usando parêntesis, e a multiplicação é geralmente denotada usando justaposição ou espaço. – f(a,b) + c d Aplica a função f à a e b, e adiciona o resultado Aplica a função f à a e b, e adiciona o resultado o produto ao produto de c e d. o produto ao produto de c e d.
  • 21. 21 Aplicação de funções (2) ● Em Haskell, a aplicação de funções é denotada usando espaço, e a multiplicação é denotada usando *: – f a b + c*d Como no exemplo anterior, só que agora na Como no exemplo anterior, só que agora na sintaxe Haskell sintaxe Haskell
  • 22. 22 Aplicação de funções (2) ● Também, a aplicação de funções tem precedência sobre todos os outros operadores: – f a + b Significa Significa ((ff aa)) ++ bb,, aaoo ccoonnttrráárriioo ddee ff ((aa ++ bb))
  • 23. 23 Aplicação de funções (Exemplos) Matemática Haskell f(x) f x f(x,y) f x y f(g(x)) f (g x) f(x,g(y)) f x (g y) f(x)g(y) f x * g y
  • 24. 24 Scripts em Haskell ● Apesar de haver funções na biblioteca padrão (prelude), é possível definir funções próprias; ● Novas funções são definidas em um script, um arquivo de texto contendo uma sequência de definições; ● Por convenção, scripts Haskell possuem extensão .hs.
  • 25. 25 Meu primeiro script ● É útil manter duas janelas abertas ao programar em Haskell. Uma para o script o outra para o Hugs; ● Abra um editor, digite as duas expressões e salve com o nome teste.hs: double x = x + x quadruple x = double (double x)
  • 26. 26 Meu primeiro script (2) ● Deixe o editor aberto e inicie o Hugs com: > hugs teste.hs ou > hugs > :load teste.hs
  • 27. 27 Meu primeiro script (3) ● Agora Prelude.hs e teste.hs estão carregados, e as funções dos dois scripts podem ser usadas: > quadruple 10 40 > take (double 2) [1,2,3,4,5,6] [1,2,3,4]
  • 28. 28 Meu primeiro script (4) ● Mantendo o Hugs aberto, retorne ao editor, adicione as definições abaixo, salve e digite :reload no Hugs: factorial n = product [1..n] average ns = sum ns `div` length ns ● Nota: – ● div é cercado por aspas invertidas (crase); ● x `f` y é apenas um syntactic sugar para f x y. ● div é cercado por aspas invertidas (crase); ● x `f` y é apenas um syntactic sugar para f x y.
  • 29. 29 Meu primeiro script (5) > factorial 10 3628800 > average [1,2,3,4,5] [1,2,3]
  • 30. 30 Requisitos para nomes ● Nomes de funções e argumentos devem iniciar em caixa baixa: myFun fun1 arg_2 x' ● Por convensão, argumentos de lista geralmente possuem o sufixo s nos seus nomes (notação húngara): xs ns nss
  • 31. 31 A regra do layout a = 10 b = 20 c = 30 a = 10 b = 20 c = 30 a = 10 b = 20 c = 30
  • 32. 32 A regra do layout (2) a = b + c where b = 1 C = 2 d = a * 2 a = b + c where {b = 1 c = 2} d = a * 2 Mesmo que AAggrruuppaammeenntoto i mimpplílcícitioto AAggrruuppaammeenntoto e exxpplílcícitioto
  • 33. 33 Exercícios ● 1. Teste os slides 17-19 e 25-29 usando Hugs; ● 2. Corrija os erros do programa abaixo, e teste sua solução usando Hugs. N = a 'div' lenght xs where a = 10 xs = [1,2,3,4,5]
  • 34. 34 Exercícios 3.Tente reescrever a função last, que seleciona o último elemento de uma lista, usando as funções vistas anteriormente; 4.Você consegue pensar em outra solução? 3.Similarmente, reescreva a função init, que remove o último elemento de uma lista.
  • 35. 35 O que é um tipo? Um tipo é um nome para uma coleção de valores relacionados. Por exemplo, o tipo básico Bool contém dois valores lógicos: False True
  • 36. 36 Erros de tipo ● Aplicar um função à um ou mais argumentos do tipo errado é chamado erro de tipo. > 1 + False Error 1 é um número e False é um valor lógico, mas 1 é um número e False é um valor lógico, mas + requer dois números + requer dois números
  • 37. 37 Tipos em Haskell ● Se ao avaliar uma expressão e produzir um valor do tipo t, então e tem o tipo t, escrito: e :: t ● Toda expressão bem formada tem um tipo, que pode ser automaticamente calculado em tempo de compilação usando um processo chamado inferência de tipo.
  • 38. 38 Tipos em Haskell (2) ● Todos os erros de tipo são verificados em tempo de compilação, o que torna os programas seguros e rápidos, removendo a necessidade de checagem de tipo em tempo de execução; ● No Hugs, o comando :type calcula o tipo de uma expressão, sem avaliá-la. > not False True > :type not False not False :: Bool
  • 39. 39 Tipos básicos em Haskell Bool Valores lógicos Char Caracteres únicos String String (fio) de caracteres Int Inteiros de precisão fixa Integer Inteiros de precisão arbitrária Float Número de ponto flutuante
  • 40. 40 Tipos Lista ● Uma lista é uma sequência de valores do mesmo tipo: [False,True,False] :: [Bool] ['a','b','c','d'] :: [Char] ● De maneria geral: [t] é o tipo de listas de elementos do tipo t.
  • 41. 41 Tipos Lista (2) ● Nota: – O tipo das listas não diz nada sobre o seu tamanho [False,True] :: [Bool] [False,True,False] :: [Bool] – O tipo dos elementos não tem restrições. Por exemplo, é possível criar listas de listas: [['a'],['b','c']] :: [[Char]]
  • 42. 42 Tipos Tupla ● Uma tupla é uma sequência de valores de tipos diferentes: (False,True) :: (Bool,Bool) (False,'a',True) :: (Bool,Char,Bool) ● De modo geral: – (t1,t2,...,tn) é o tipo de n-tuplas quais os iésimos componentes têm o tipo ti para qualquer i em 1..n.
  • 43. 43 Tipos Tupla (2) ● Nota: – O tipo de uma tupla codifica seu tamanho: (False,True) :: (Bool,Bool) (False,True,False) :: (Bool,Bool,Bool) – Não há restrições para o tipo dos componentes: ('a',(False,'b')) :: (Char,(Bool,Char)) (True,['a','b']) :: (Bool,[Char])
  • 44. 44 Tipos Função ● Uma função é um mapeamento de valores de um tipo para valores de outro tipo: not :: Bool → Bool isDigit :: Char → Bool ● De maneira geral: – t1 → t2 é o tipo das funções que mapeia valores do tipo t1 para valores do tipo t2.
  • 45. 45 Tipos Função (2) ● Nota: – A flecha → é digitada no teclado como ->; – Não há restrições para o tipo de argumento e resultados. Por exemplo, funções com múltiplos argumentos ou resultados são possíveis usando listas ou tuplas. add :: (Int,Int) → Int add (x,y) = x + y zeroto :: Int → [Int] zeroto n = [0..n]
  • 46. 46 Funções Arranjadas (Curried) ● Funções com múltiplos argumentos que retornam funções como resultado: add' :: Int → (Int → Int) add' x y :: x + y add' toma um valor inteiro x e retorna uma função add' x. Por sua vez, esta função toma um inteiro y add' toma um valor inteiro x e retorna uma função add' x. Por sua vez, esta função toma um inteiro y e retorna o resultado de x + y. e retorna o resultado de x + y.
  • 47. 47 Funções Arranjadas (Curried) (2) ● Nota: – add e add' produzem o mesmo resultado final, mas add toma seus dois argumentos ao mesmo tempo, enquanto add' toma um de cada vez: add :: (Int,Int) → Int add' :: Int → (Int → Int) ● Funções que tomam um argumento por vez são chamadas funções arranjadas ou curried, em homenagem a Haskell Curry.
  • 48. 48 Funções Arranjadas (Curried) (3) ● Funções com mais de dois argumentos podem ser arranjadas retornando funções aninhadas: mult :: Int → (Int → (Int → Int)) mult x y z = x*y*z mult toma um inteiro x e retorna uma função mult x, que por sua vez toma um inteiro y e retorna uma função mult mult toma um inteiro x e retorna uma função mult x, que por sua vez toma um inteiro y e retorna uma função mult x y, que finalmente toma um inteiro z e retorna o x y, que finalmente toma um inteiro z e retorna o resultado x * y * z. resultado x * y * z.
  • 49. 49 Por que Currying é útil? ● Funções curried são mais flexíveis que funções em tuplas, porque funções úteis muitas vezes podem ser construídas aplicando parcialmente uma função curried. ● Por exemplo: add' 1 :: Int → Int take 5 :: [Int] → [Int] drop 5 :: [Int] → [Int]
  • 50. 50 Convensões de curring ● Para evitar excesso de parênteses quando usa-se funções curried, duas convenções simples são adotadas: – A flecha → associa à direita. Int → Int → Int → Int SSiiggnniiffiiccaa IInntt →→ ((IInntt →→ ((IInntt →→ IInntt))))
  • 51. 51 Convensões de curring (2) ● Por consequência, é natural aplicar uma função associando a esquerda. mult x y z SSiiggnniifficicaa ((((mmuultlt xx)) yy)) zz ● A não ser que tuplas sejam requeridas, todas as funções em Haskell são normalmente definidas na forma curried.
  • 52. 52 Funções Polimórficas ● Uma função é chamada polimórfica (“de muitas formas”) se seu tipo contém uma ou mais variáveis de tipo. length :: [a] → Int Para qualquer tipo a, length toma uma lista de valores do tipo a e retorna um inteiro. Para qualquer tipo a, length toma uma lista de valores do tipo a e retorna um inteiro.
  • 53. 53 Funções Polimórficas (2) ● Nota: – Variáveis de tipo podem ser instanciadas para diferentes tipos em diferentes circunstâncias: > length [False,True] 2 > length [1,2,3,4] 4 aa == BBooooll aa == IInntt – Variáveis de tipo devem começar com letras minúsculas, e usualmente são nomeadas a, b, c, etc.
  • 54. 54 Funções Polimórficas (3) ● Várias funções do prelude são polimórficas: fst :: (a,b) → a head :: [a] → a take :: Int → [a] → [a] zip :: [a] → [b] → [(a,b)] id :: a → a
  • 55. Char não é um tipo numérico 55 Funções Polimórficas (4) ● Variáveis de tipo restrito podem ser instanciadas para qualquer tipo que satisfaça a restrição. > sum [1,2,3] 6 > sum [1.1,2.2,3.3] 6.6 > sum ['a','b','c'] ERROR aa == IInntt aa == FFllooaatt Char não é um tipo numérico
  • 56. 56 Funções Polimórficas (5) ● Haskell possui várias classes de tipo, incluindo: – Num – Tipos numéricos – Eq – Tipos de igualdade – Ord – Tipos de relação (ordenação) ● Por exemplo: (+) :: Num a => a → a → a (==) :: Eq a => a → a → Bool (<) :: Ord a => a → a → Bool
  • 57. 57 Dicas e Sugestões ● Ao definir uma nova função em Haskell, é útil iniciar escrevendo seu tipo; ● Em um script, é uma boa prática definir o tipo de todas as novas funções; ● Quando definir os tipos de funções polimórficas que utilizam números, igualdades ou relações, tenha cuidado em incluir as classes de restrições necessárias.
  • 58. 58 Dicas e Sugestões add :: Num a => a -> a -> a add x y = x + y
  • 59. 59 Exercícios ● Quais são os tipos dos seguintes valores? ['a','b','c'] ('a','b','c') [(False,'0'),(True,'1')] [(False,True),('0','1')] [tail,init,reverse]
  • 60. 60 Exercícios ● Quais são os tipos das seguintes funções? second xs = head (tail xs) swap (x,y) = (y,x) pair x y = (x,y) double x = x*2 palindrome xs = reverse xs == xs twice f x = f(f x) ● Verifique suas respostas usando o Hugs.
  • 61. 61 Expressões Condicionais ● Na maioria das linguagens de programação, funções podem ser definidas usando expressões condicionais. abs :: Int → Int abs n = if n >= 0 then n else -n abs toma um inteiro n se n for não-negativo, abs toma um inteiro n se n for não-negativo, senão, retorna -n. senão, retorna -n.
  • 62. 62 Expressões Condicionais ● Expressões condicionais podem ser aninhadas: signum :: Int → Int signum n = if n < 0 then -1 else ● Nota: if n == 0 then 0 else 1 – Em Haskell, expressões condicionais sempre devem ter o desvio senão (else), que evita ambiguidades com expressões aninhadas.
  • 63. 63 Equações restritas (Guarded Equations) ● Com alternativa para expressões, funções também podem ser definidas usado equações restritas: abs n | n >= 0 = n | otherwise = -n Como o anterior, m Como o anterior, maass uussaannddoo gguuaarrddeedd..
  • 64. 64 Equações restritas (Guarded Equations) ● Equações restritas podem ser usadas para simplificar a leitura de definições que envolvem múltiplas condições: ● Nota: signum n | n < 0 = -1 | n == 0 = 0 | otherwise = 1 – A condição otherwise é definida no prelude por otherwise = True.
  • 65. 65 Pattern Matching ● Muitas funções possuem uma definição mais clara utilizando pattern matching (casamento de padrões) nos seus argumentos: not :: Bool → Bool not False = True not True = False not mapeia False para not mapeia False para TTrruuee,, ee TTrruuee ppaarraa FFaallssee
  • 66. 66 Pattern Matching (2) (&&) :: Bool → Bool → Bool True && True = True _ && _ = False WWiillddccaarrdd (&&) :: Bool → Bool → Bool True && x = True , x == True = False , x == False False && x = False , x == False = False , x == True
  • 67. 67 Pattern Matching (3) (&&) :: Bool → Bool → Bool True && True = True True && False = False False && True = False False && False = False (&&) :: Bool → Bool → Bool True && b = b False && _ = False
  • 68. 68 Pattern Matching (4) ● Padrões são casados segundo a ordem top → bottom, left → rigth. Por exemplo, a seguinte definição sempre retorna False: _ && _ = False True && True = True ● Padrões não podem repetir variáveis. Por exemplo, a seguinte definição causa um erro: b && b = b _ && _ = False
  • 69. 69 Padrões de Listas ● Internamente, toda lista não-vazia é construída pelo uso repetido do operador (:) chamado “cons” que adiciona um elemento ao início da lista. [1,2,3,4] SSiiggnniiffiiccaa 11::((22::((33::((44::[[]]))))))
  • 70. 70 Padrões de Listas ● Funções em listas podem ser definidas utilizando padrões x:xs. head :: [a] → a head (x:_) = x tail :: [a] → [a] tail (_:xs) :: xs head e tail mapeia qualquer lista não-vazia para head e tail mapeia qualquer lista não-vazia para seus primeiros e últimos elementos seus primeiros e últimos elementos
  • 71. 71 Padrões de Listas ● Nota: – O padrão x:xs somente casa listas não-vazias: > head [] Error – Padrões x:xs devem ser parentesados, por que a aplicação do padrão tem prioridade sobre (:). Por exemplo, a seguinte definição retorna um erro: head x:_ = x
  • 72. 72 Padrões de Inteiros ● Como na matemática, funções em inteiros podem ser definidas usando o padrão n+k, onde n é uma variável inteira e k>0 é uma constante inteira. pred :: Int → Int pred (n+1) = n pred mapeia qualquer inteiro positivo para seu predecessor pred mapeia qualquer inteiro positivo para seu predecessor
  • 73. 73 Padrões de Inteiros fac :: Int → Int fac 0 = 1 fac (n+1) = n + (fac n)
  • 74. 74 Padrões de Inteiros ● Nota: – Padrões n+k casam somente inteiros ≥ k. > pred 0 Error – Padrões n+k devem ser parentesados, porque a aplicação tem prioridade sobre +. Por exemplo, a seguinte definição resulta em um erro: pred n+1 = n
  • 75. 75 Expressões Lambda ● Funções podem ser construídas sem serem nomeadas usado expressões lambda. λx → x + x uma função sem nome que toma um número x e retorna o uma função sem nome que toma um número x e retorna o resultado x+x resultado x+x
  • 76. 76 Expressões Lambda ● Em Haskell: Int -> Int x -> x + x
  • 77. 77 Expressões Lambda ● Nota: – O símbolo λ é a letra Grega lambda, e é escrita no teclado com ; – Na matemática, funções sem nome são usualmente denotadas usado o símbolo ↦, como em x ↦ x + x; – Em Haskell, o uso do símbolo λ para funções sem nome vem do cálculo lambda, a teoria de funções no qual Haskell é baseado.
  • 78. 78 Por que Lambdas são úteis? Expressões lambda poder ser usadas para dar um significado formal para funções definidas com currying. Por exemplo: significa add x y = x + y add = λx → (λy → x + y)
  • 79. 79 Por que Lambdas são úteis? Expressões lambda também são úteis ao definir funções que retornam funções como resultado. Por exemplo: const :: a → b → a const x _ = x é mais naturalmente definido por const :: a → (b → a ) const x = λ_ x → x
  • 80. 80 Por que Lambdas são úteis? Expressões lambda poder ser usadas para evitar dar nomes a funções que são referenciadas uma vez apenas. Por exemplo: odds n = map f [0..n-1] where f x = x*2 + 1 Pode ser simplificado para odds n = map (λx → x*2 + 1) [0..n-1]
  • 81. 81 Seções ● Um operador escrito entre seus dois argumentos pode ser convertido em uma função curried escrita antes de seus dois argumentos usando parênteses. ● Por exemplo: > 1 + 2 3 > (+) 1 2 3
  • 82. 82 Seções ● Esta convenção ainda permite que um dos argumentos do operador seja incluído nos parênteses. ● Por exemplo: > (1+) 2 3 > (+2) 1 3 ● Geralmente, se é ⊕ um operador, então funções na forma (⊕), (x⊕) e (⊕y) são chamadas seções.
  • 83. 83 Por que seções são úteis? Funções úteis as vezes podem ser construídas de uma maneira simples utilizando seções. Por exemplo: (1+) – função sucessor (1/) – função recíproca (*2) – função para dobrar (/2) – função para dividir ao meio
  • 84. 84 Exercícios 1.Considere a função safetail que tem o mesmo comportamento da função tail, exceto por safetail mapear lista vazia para lista vazia, sendo que tail retorna um erro neste caso. – Defina safetail usando: ● Uma expressão condicional; ● Uma expressão abrigada (guarded); ● Casamento de padrões. – Dica: a função null :: [a] → Bool pode ser usada para verificar se uma lista é vazia.
  • 85. 85 Exercícios 2.Crie três possíveis definições para o operador lógica (||) usando casamento de padrões; 3.Redefina a seguinte versão de (&&) usando expressões condicionais ao invés de casamento de padrões: True && True = True _ && _ = False 6.Faça o mesmo para a seguinte versão: True && b = b False && _ = False
  • 86. 86 Listas por Compreensão (List Comprehensions) ● Na matemática, a notação por compreensão pode ser usada para construir novos conjuntos a partir de conjuntos antigos. O conjunto {1,4,9,16,25} de todos os números x2 tal que x seja um elemento do conjunto {1...5} O conjunto {1,4,9,16,25} de todos os números x2 tal que x seja um elemento do conjunto {1...5}
  • 87. 87 Listas por Compreensão (2) ● Em Haskell, um notação por compreensão similar pode ser usada para construir novas listas a partir de listas antigas. [x^2 | x ← [1..5]] A lista [1,4,9,16,25] de todos os números x^2 tal que x seja um elemento da lista [1..5] A lista [1,4,9,16,25] de todos os números x^2 tal que x seja um elemento da lista [1..5]
  • 88. 88 Listas por Compreensão (3) ● Nota: – A expressão x ← [1..5] é chamada geradora, pois ela define como gerar os valores para x; – Compreensões podem ter várias geradoras, separadas por vírgula. Por exemplo: > [(x,y) | x ← [1,2,3], y ← [4,5]] [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)]
  • 89. 89 Listas por Compreensão (4) ● Nota: – Alterando a ordem das geradoras altera a ordem dos elementos na lista final: > [(x,y) | x ← [4,5], y ← [1,2,3]] [(1,4),(2,4),(3,4),(1,5),(2,4),(3,5)] – Múltiplas geradoras são como laços aninhados, sendo as últimas geradoras são os laços mais profundos onde os valores das variáveis se alteram com mais frequência.
  • 90. 90 Listas por Compreensão (5) ● Por exemplo: > [(x,y) | x ← [4,5], y ← [1,2,3]] [(1,4),(2,4),(3,4),(1,5),(2,4),(3,5)] x ← [1,2,3] é a última geradora, sendo assim x ← [1,2,3] é a última geradora, sendo assim o valor do componente x se altera com mais frequência o valor do componente x se altera com mais frequência
  • 91. 91 Geradoras Dependentes ● As últimas expressões geradoras podem depender de variáveis introduzidas nas primeiras geradoras. [(x,y) | x ← [1..3], y ← [x..3]] A lista [(1,1),(1,2),(1,3),(2,2),(2,3),(3,3)] de todos os pares dos números (x,y) A lista [(1,1),(1,2),(1,3),(2,2),(2,3),(3,3)] de todos os pares dos números (x,y) tal que x,y sejam elementos da lista [1..3] e y >= x tal que x,y sejam elementos da lista [1..3] e y >= x
  • 92. 92 Geradoras Dependentes ● Usando uma expressão geradora dependente pode-se definir uma função de biblioteca que concatena uma lista de listas. concat :: [[a]] → [a] concat xss = [x | xs ← xss, x ← xs] ● Por exemplo: concat [[1,2,3],[4,5],[6]] [1,2,3,4,5,6]
  • 93. 93 Guards ● Listas por compreensão podem usar “guards” para restringir o valor produzido pelas primeiras geradoras. [x | x ← [1..10], even x] A lista [2,4,6,8,10] A lista [2,4,6,8,10] de todos os números x tal que x seja um elemento da lista [1..10] e x seja par de todos os números x tal que x seja um elemento da lista [1..10] e x seja par
  • 94. [x | x <- [1..n], n `mod` x == 0] 94 Guards ● Usando “guards” é possível definir uma função que mapeia um número inteiro positivo para sua lista de fatores: factors :: Int -> [Int] factors n = ● Por exemplo: > factors 15 [1,3,5,15]
  • 95. 95 Guards ● Um inteiro positivo é primo se seus únicos fatores forem 1 e ele mesmo. Sendo assim, usando factors é possível definir uma função que decide se um número é primo: prime :: Int → Bool prime n = factors n == [1,n] ● Por exemplo: > prime 15 False > prime 7 True
  • 96. 96 Guards ● Agora, usando “guards” é possível definir uma função que retorna a lista de todos os primos até um dado limite: primes ::Int → [Int] primes n = [x | x ← [2..n], prime x] ● Por exemplo: > primes 40 [2,3,5,7,11,13,17,19,23,29,31,37]
  • 97. 97 A função Zip ● Uma função de biblioteca muito útil, qual mapeia duas listas para uma lista de pares de seus elementos correspondentes. zip :: [a] → [b] → [(a,b)] ● Por exemplo: > zip ['a','b','c'][1,2,3,4] [('a',1),('b',2),('c',3)]
  • 98. 98 A função Zip ● Usando zip é possível definir uma função que retorna uma lista de todos os pares de elementos adjacentes de outra lista: pairs :: [a] → [(a,a)] pairs xs = zip xs (tail xs) ● Por exemplo: > pairs [1,2,3,4] [(1,2),(2,3),(3,4)]
  • 99. ● Usando pairs é possível definir uma função que decide se os elementos de uma lista estão ordenados: 99 sorted :: Ord a => [a] → Bool sorted xs = and [x <= y | (x,y) ← pairs xs] ● Por exemplo: > sorted [1,2,3,4] True > sorted [1,3,2,4] False
  • 100. ● Usando zip é possível definir uma função que retorna uma lista de todas as posições de um valor em uma lista: 100 positions :: Eq a => a → [a] → [Int] positions x xs = [i | (x',i) ← zip xs [0..n], x == x'] where n = length xs - 1 ● Por exemplo: > positions 0 [1,0,0,1,0,1,1,0] [1,2,4,7]
  • 101. 101 Compreensões em String ● Uma string é uma sequência de caracteres cercadas por aspas duplas. Internamente, no entanto, strings são representadas como listas de caracteres. “abc” :: String Significa Significa [['a'a',','b'b',','c'c']'] :::: [[CChhaarr]]
  • 102. 102 ● Similarmente, compreensões em strings podem ser usadas para definir funções em strings como, por exemplo, uma função que conta as letras minúsculas (caixa-baixa) em uma string: lowers :: String → Int lowers xs = length [x | x ← xs, isLower x] ● Por exemplo: > lowers “Haskell” 6
  • 103. 103 Exercícios 1. Um tripla (x,y,z) de inteiros positivos é chamada de pitagórica se x² + y² = z². Usando uma compreensão em lista, defina a função pyths :: Int → [(Int,Int,Int)] que mapeia um inteiro n para todas as triplas com componentes em [1..n]. Por exemplo: > pyths 5 [(3,4,5),(4,3,5)]
  • 104. 104 Exercícios 2. Um inteiro positivo é perfeito se for igual à soma de todos os seus fatores, excluindo o próprio número. Usando uma compreensão de lista, defina uma função perfects :: Int → [Int] que retorne a lista de todos os números perfeitos até um dado limite. Por exemplo: > perfects 500 [6,28,496]
  • 105. 105 Leitura Hughes, John. Why Functional Programming Matters http://www.cse.chalmers.se/~rjmh/Papers/whyfp.pdf
  • 106. 106 Funções recursivas ● Como visto, muitas funções podem ser definidas em termos de outras funções. factorial :: Int → Int factorial n = product [1..n] factorial mapeia qualquer inteiro n para o produto dos factorial mapeia qualquer inteiro n para o produto dos inteiros entre 1 e n inteiros entre 1 e n
  • 107. 107 Funções recursivas (2) ● Expressões são avaliadas em um processo passo-a-passo de aplicação de funções em seus argumentos. ● Por exemplo: factorial 4 = product [1..4] = product [1,2,3,4] = 1*2*3*4 = 24
  • 108. 108 Funções recursivas (3) product :: [Int] → Int product [] = 1 product (x:xs) = x * product xs .... fact 4 [1,2,3,4] = product (1:(2:(3:(4:[])))) = 1 * product (2:(3:(4:[]))) . . .
  • 109. 109 Funções recursivas (4) ● Em Haskell, funções podem ser definidas em termos delas mesmas. Tal funções são chamadas recursivas. factorial 0 = 1 factorial (n+1) = (n+1) * factorial n factorial mapeia 0 para 1, e qualquer outro inteiro positivo para o produto dele mesmo com o fatorial de factorial mapeia 0 para 1, e qualquer outro inteiro positivo para o produto dele mesmo com o fatorial de seu predecessor. seu predecessor.
  • 110. 110 Funções recursivas (5) factorial 3 = 3 * factorial 2 = 3 * (2 * factorial 1) = 3 * (2 * (1 * factorial 0)) = 3 * (2 * (1 * 1)) = 3 * (2 * 1) = 3 * 2 = 6
  • 111. 111 Funções recursivas (nota) ● factorial 0 = 1 é apropriado pois 1 é o valor identidade da multiplicação: 1*x = x = x*1 ● A definição da função recursiva diverge em inteiros < 0 porque o caso base nunca é alcançado: > factorial (-1) Error: Control stack overflow
  • 112. 112 Porque recursão é útil ● Algumas funções, como factorial, são mais simples de definir em termos de outras funções. ● Como visto, no entanto, muitas funções podem ser naturalmente definidas em termos delas mesmas. ● Propriedades de funções definidas usando recursão podem ser provadas usando uma simples porém poderosa técnica matemática de indução.
  • 113. 113 Recursões em listas ● Recursão não se restringe à números, mas também pode ser usado para definir funções em listas. product :: [Int] → Int product [] = 1 product (x:xs) = x * product xs product mapeia a lista vazia para 1, e qualquer outra lista não-vazia para sua cabeça multiplicada pelo product mapeia a lista vazia para 1, e qualquer outra lista não-vazia para sua cabeça multiplicada pelo produto de sua calda. produto de sua calda.
  • 114. 114 Recursões em listas (2) product [2,3,4] = 2 * product [3,4] = 2 * (3 * product[4]) = 2 * (3 * ( * 4 * product[]) = 2 * (3 * (4 * 1)) = 24
  • 115. 115 Recursões em listas (3) ● Usando o mesmo padrão de recursão como em product pode-se definir a função length em listas. length :: [a] → Int length [] = 0 length (_:xs) = 1 + length xs length mapeia um lista vazia para 0, e qualquer outra lista não-vazia para o sucessor do comprimento de length mapeia um lista vazia para 0, e qualquer outra lista não-vazia para o sucessor do comprimento de sua calda. sua calda.
  • 116. 116 Recursões em listas (4) length [1,2,3] = 1 + length [2,3] = 1 + (1 + length [3]) = 1 + (1 + (1 + (length [])) = 1 + (1 + (1 + (0)) = 3
  • 117. 117 Recursões em listas (5) ● Usando um padrão similar de recursão pode-se definir a função reverse em listas. reverse :: [a] → [a] reverse [] = [] reverse (x:xs) = reverse xs ++ [x] reverse mapeia um lista vazia outra lista vazia, e qualquer outra lista não-vazia para o reverso da sua reverse mapeia um lista vazia outra lista vazia, e qualquer outra lista não-vazia para o reverso da sua calda concatenada com a cabeça. calda concatenada com a cabeça.
  • 118. 118 Recursões em listas (4) reverse [1,2,3] = reverse [2,3] ++ [1] = (reverse [3] ++ [2]) ++ [1] = ((reverse [] ++ [3] ++ [2]) ++ [1] = (([] ++ [3] ++ [2]) ++ [1] = [3,2,1]
  • 119. 119 Múltiplos argumentos em recursão ● Funções com mais de um argumento também podem ser definidas usando recursão. ● Por exemplo, zipping os elementos de duas listas: zip :: [a] → [b] → [(a,b)] zip [] _ = [] zip _ [] = [] zip (x:xs) (y:ys) = (x,y) : zip xs ys
  • 120. 120 Múltiplos argumentos em recursão (2) ● Remover os primeiros n elementos de uma lista: drop :: Int → [a] → [a] drop 0 xs = xs drop (n+1) [] = [] drop (n+1) (_:xs) = drop n xs ● Concatenar duas listas: (++) :: [a] → [a] → [a] [] ++ ys = ys (x:xs) ++ ys = x : (xs ++ ys)
  • 121. 121 Quicksort ● O algoritmo quicksort para ordenar uma lista de inteiros pode ser especificado pelas duas regras seguintes: – Uma lista vazia já está ordenada; – Listas não-vazias podem ser ordenadas ordenando os valores da cauda <= à cabeça, ordenando os valores da cauda > que a cabeça, e concatenando as duas listas resultantes em cada lado do valor da cabeça.
  • 122. 122 Quicksort (2) ● Usando recursão, esta especificação pode ser traduzida diretamente para uma implementação: qsort :: [Int] -> [Int] qsort [] = [] qsort (x:xs) = qsort menores ++ [x] ++ qsort maiores where menores = [a | a <- xs, a <= x] maiores = [b | b <- xs, b > x] Nota: Esta é provavelmente a implementação mais simples de quicksort em qualquer linguagem de programação. Nota: Esta é provavelmente a implementação mais simples de quicksort em qualquer linguagem de programação.
  • 123. 123 Quicksort (3) qq [[33,,22,,44,,11,,55]] qq [[22,,11]] ++++ [[33]] ++++ qq [[44,,55]] qq [[11]] ++++ [[22]] ++++ qq [[]] qq [[]] ++++ [[44]] ++++ qq [[55]] [[11]] [[]] [[]] [[55]]
  • 124. 124 Exercícios ● Sem olhar no prelude padrão, defina as seguinte biblioteca de funções usando recursão: – Verificar se todos os valores em uma lista são verdadeiros: and :: [Bool] → Bool – Concatenar uma lista de listas: concat :: [[a]] → [a] – Produzir uma lista com n elementos idênticos: replicate :: Int → a → [a] – Selecionar o iésimo elemento de uma lista: (!!) :: [a] → Int → a – Verificar se um valor é um elemento de da lista: elem :: Eq a => a → [a] → Bool
  • 125. 125 Haskell Capítulo 7 – Funções de Alta Ordem (Funções de Ordem Superior)
  • 126. 126 Introdução ● Uma função é chamada de alta ordem se ela toma uma função como argumento ou retorna uma função como resultado. twice :: (a → a) → a → a twice f x = f (f x) twice é uma função de alta ordem porque toma uma twice é uma função de alta ordem porque toma uma função como seu primeiro argumento função como seu primeiro argumento
  • 127. 127 Porque são tão úteis? ● Idiomas comuns de programação podem ser codificados como funções dentro própria linguagem. ● Linguagens de domínio específico podem ser definidas como coleções de funções de alta ordem. ● Propriedades algébricas de funções de alta ordem podem ser usadas para raciocinar sobre programas.
  • 128. 128 A função map ● A função de alta ordem da biblioteca chamada map aplica uma função para cada elemento de uma lista. map :: (a → b) → [a] → [b] ● Por exemplo: > map (+1) [1,3,5,7] [2,4,6,8]
  • 129. 129 A função map (2) ● A função map pode ser definida em uma maneira particularmente simples usando compreensão de lista. map f xs = [f x | x ← xs] Alternativamente, para provar, a função map pode ser definida utilizando recursão: map f [] = [] map f (x:xs) = f x : map f xs
  • 130. 130 A função filter ● A função de alta ordem filter seleciona todos os elementos de uma lista que satisfazem um predicado. filter :: (a → Bool) → [a] → [a] ● Por exemplo: > filter even [1..10] [2,4,6,8,10]
  • 131. 131 A função filter (2) ● Filter pode ser definida utilizando compreensão de lista. filter p xs = [x | x ← xs, p x] Alternativamente, pode ser definida utilizando recursão: filter p [] = [] filter p (x:xs) | p x = x : filter p xs | otherwise = filter p xs
  • 132. 132 A função foldr ● Várias funções em listas podem ser definidas utilizando o seguinte padrão simples: f [] = v f (x:xs) = x ⊕ f xs f mapeia um lista vazia para algum valor v, e qualquer outra lista não vazia para alguma uma função ⊕ aplicada na cabeça e f na calda f mapeia um lista vazia para algum valor v, e qualquer outra lista não vazia para alguma uma função ⊕ aplicada na cabeça e f na calda
  • 133. 133 A função foldr (2) - Exemplo sum [] = 0 sum (x:xs) = x + sum xs v = 0 v = 0 ⊕ = + ⊕ = + product [] = 1 product (x:xs) = x * product xs v = 1 ⊕ = * v = 1 ⊕ = * and [] = True and (x:xs) = x && and xs v = True ⊕ = && v = True ⊕ = &&
  • 134. 134 A função foldr (3) ● A função de alta ordem foldr (fold right) encapsula este padrão de recursão simples, juntamente com a função ⊕ e o valor v como argumentos. sum = foldr (+) 0 product = foldr (*) 1 or = foldr (||) False and = foldr (&&) True
  • 135. 135 A função foldr (4) ● foldr pode ser definida usando recursão: foldr :: (a -> b -> b) -> b -> [a] -> b foldr f v [] = v foldr f v (x:xs) = f x (foldr f v xs) ● No entanto, é melhor pensar em foldr de forma não recursiva, simultaneamente substituindo cada (:) em uma lista para um função dada, e [] para um valor dado.
  • 136. 136 A função foldr (5) sum [1,2,3] = foldr (+) 0 [1,2,3] = foldr (+) 0 (1:(2:(3:[]))) = 1+(2+(3+0)) = 6 Substitua cada (:) por (+) e [] por 0 Substitua cada (:) por (+) e [] por 0
  • 137. 137 A função foldr (6) product [1,2,3] = foldr (*) 1 [1,2,3] = foldr (*) 1 (1:(2:(3:[]))) = 1*(2*(3*1)) = 6 Substitua cada (:) por (*) e [] por 1 Substitua cada (:) por (*) e [] por 1
  • 138. 138 A função foldr (7) ● Mesmo foldr encapsulando um padrão de recursão simples, ela pode ser usada para definir muitas outras funções do que se possa esperar. ● Relembrando a função length: length :: [a] -> Int length [] = 0 length (_:xs) = 1 + length xs
  • 139. Substitua cada (:) por λ_ n → 1+n e 139 A função foldr (8) length [1,2,3] = length (1:(2:(3:[]))) = 1+(1+(1+0)) = 3 Substitua cada (:) por λ_ n → 1+n e [] por 0 [] por 0 length = foldr (_ n -> 1+n) 0
  • 140. Reverse [] = [] reverse (x:xs) = reverse xs ++ [x] Substitua cada (:) por λx xs → xs ++ 140 A função foldr (9) reverse [1,2,3] = reverse (1:(2:(3:[]))) = (([] ++ [3]) ++ [2]) ++ [1] = [3,2,1] Substitua cada (:) por λx xs → xs ++ [x] e [] por [] [x] e [] por [] ● Agora relembrando a função reverse:
  • 141. Substitua cada (:) por (:) [] por ys 141 A função foldr (10) ● Portanto, nós temos: (++ ys) = foldr (:) ys Substitua cada (:) por (:) [] por ys reverse = foldr (x xs -> xs ++ [x]) [] ● Finalmente, nota-se que a função de concatenação (++) tem uma definição particularmente compacta utilizando foldr:
  • 142. 142 Por que foldr é útil? ● Algumas funções recursivas em listas, como sum, são mais simples de definir usando foldr; ● Propriedades de funções definidas usando foldr podem ser provadas usando propriedades algébricas de foldr, como fusão e a regra da banana split; ● Otimizações avançadas de programa podem ser simples se foldr é usado ao invés de recursão explícita.
  • 143. (.) :: (b -> c) -> (a -> b) -> (a -> c) f . g = x -> f (g x) 143 Outras funções de biblioteca ● A função de biblioteca (.) retorna a composição de duas funções como um única função. ● Por exemplo: odd :: Int -> Bool odd = not . even
  • 144. 144 Outras funções de biblioteca (2) ● A função de biblioteca all decide se todos os elementos de uma lista satisfazem um dado predicado. all :: (a -> Bool) -> [a] -> Bool all p xs = and [p x | x <- xs] ● Por exemplo: > all even [2,4,6,8,10] True
  • 145. 145 Outras funções de biblioteca (3) ● Similarmente, a função de biblioteca any decide se pelo menos um elemento de uma lista satisfaz um dado predicado. any :: (a -> Bool) -> [a] -> Bool any p xs = or [p x | x <- xs] ● Por exemplo: > any isSpace "abc def" True
  • 146. takeWhile :: (a -> Bool) -> [a] -> [a] takeWhile p [] = [] takeWhile p (x:xs) 146 Outras funções de biblioteca (4) ● A função de biblioteca takeWhile seleciona elementos de uma lista enquanto um predicado for verdadeiro. | p x = x : takeWhile p xs | otherwise = [] ● Por exemplo: > takeWhile isAlpha "abc def" "abc"
  • 147. dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p (x:xs) 147 Outras funções de biblioteca (5) ● A função de biblioteca takeWhile seleciona elementos de uma lista enquanto um predicado for verdadeiro. | p x = dropWhile p xs | otherwise = x:xs ● Por exemplo: > dropWhile isSpace " abc" "abc"
  • 148. 148 Exercícios ● Expresse a compreensão [f x | x ← xs, p x] utilizando as funções map e filter. ● Redefina map f e filter p usando foldr.
  • 150. 150 O que é um analisador (parser)? ● Um analisador é um programa que analisa um trecho de texto para determinar sua estrutura sintática. 2*3+4 significa + * 4 2 3
  • 151. 151 Para que são utilizados? ● Praticamente todos programas do cotidiano usam alguma forma análise para pré-processar suas entradas: Hugs Unix Browser analisa Programas Haskell Scripts de shell Documentos HTML
  • 152. 152 O tipo Parser ● Em uma linguagem funcional como Haskell, analisadores podem ser vistos naturalmente como funções: type Parser = String -> Tree Um analisador é uma função que toma uma string e Um analisador é uma função que toma uma string e retorna alguma forma de árvore retorna alguma forma de árvore
  • 153. 153 O tipo Parser (2) ● No entanto, um analisador pode não requerer toda sua string de entrada, sendo assim também é retornada a entrada não utilizada. type Parser = String -> (Tree,String) ● Uma string pode ser analisada de várias maneiras, incluindo nenhuma, então generaliza-se para uma lista de resultados: type Parser = String -> [(Tree,String)]
  • 154. 154 O tipo Parser (3) ● Finalmente, um analisador nem sempre pode produzir uma árvore, então generaliza-se para uma valor de qualquer tipo: type Parser = String -> [(a,String)] Nota: Para simplificar, esta sendo considerado somente analisadores que ou falham e retornam um lista vazia de resultados, ou têm sucesso e retornam uma lista singleton (apenas um valor). Nota: Para simplificar, esta sendo considerado somente analisadores que ou falham e retornam um lista vazia de resultados, ou têm sucesso e retornam uma lista singleton (apenas um valor).
  • 155. 155 Analisadores básicos ● O analisador item falha se a entrada é vazia, e consome o primeiro caractere caso contrário: item :: Parser Char item = inp -> case inp of [] -> [] (x:xs) -> [(x,xs)]
  • 156. 156 Analisadores básicos (2) ● O analisador failure sempre falha: failure :: Parser a failure = inp -> [] ● O analisador return sempre tem sucesso, retornando o valor v sem consumir nenhuma entrada: return :: a -> Parser a return v = inp -> [(v,inp)]
  • 157. 157 Analisadores básicos (2) ● O analisador p +++ q se comporta como o analisador p se tiver sucesso, e como o analisador q caso contrário: (+++) :: Parser a -> Parser a -> Parser a p +++ q = inp -> case p inp of [] -> parse q inp [(v,out)] -> [(v,out)] ● A função parse aplica um analisador a uma string: parse :: Parser a -> String -> [(a,String)] parse p inp = p inp
  • 158. 158 Exemplos ● O comportamento dos cinco analisadores primitivos podem ser ilustrados com exemplos simples: % hugs parse.hs > parse item “” [] > parse item “abc” [('a',”bc”)]
  • 159. 159 Exemplos (2) > parse failure "abc" [] > parse (return 1) "abc" [(1,"abc")] > parse (item +++ return 'd') "abc" [('a',"bc")] > parse (failure +++ return 'd') "abc" [('d',"abc")]
  • 160. 160 Nota ● O arquivo de biblioteca Parsing está disponível na web na home page de Programming in Haskell. ● O tipo Parser é um monad, uma estrutura matemática que ser provou útil na modelagem de vários tipos de computações diferentes.
  • 161. 161 Sequenciamento ● Uma sequência de analisadores pode ser combinada um um único analisador composto utilizando a palavra-chave do. ● Por exemplo: p :: Parser (Char, Char) p = do x <- item item y <- item return (x,y)
  • 162. 162 Sequenciamento (2) ● Se qualquer analisador em uma sequência de analisadores falhar, então a sequência interia falhará. Por exemplo: > parse p "abcdef" [(('a','c'), "def")] > parse p "ab" [] ● A notação do não é especificada no tipo Parser, mas pode ser utilizada com qualquer tipo monadico.
  • 163. 163 Primitivas derivadas ● Analisando um caractere que satisfaz um predicado: sat :: (Char -> Bool) -> Parser Char sat p = do x <- item if p x then return x else failure
  • 164. 164 Primitivas derivadas (2) ● Analisando um dígito e caracteres específicos: digit :: Parser Char digit = sat isDigit char :: Char -> Parser Char char x = sat (x ==) ● Aplicando um analisador zero ou mais vezes: many :: Parser a -> Parser [a] many p = many1 p +++ return []
  • 165. 165 Primitivas derivadas (3) ● Aplicando um analisador uma ou mais vezes: many1 :: Parser a -> Parser [] many1 p = do v <- p vs <- many p return (v:vs) ● Analisando um string de caracteres específica: string :: String -> Parser String string [] = return [] string (x:xs) = do char x string xs return (x:xs)
  • 166. 166 Exemplo ● Agora é possível definir um analisador que consome um lista de um ou mais dígitos de uma string: p :: Parser String p = do char '[' d <- digit ds <- many (do char ',' digit) char ']' return (d:ds)
  • 167. 167 Exemplo (2) ● Agora é possível definir um analisador que consome um lista de um ou mais dígitos de uma string: > parse p "[1,2,3,4]" [("1234","")] > parse p "[1,2,3,4" [] Nota: Bibliotecas de análise mais sofisticadas podem indicar e/ou recuperar-se de erros na string de entrada. Nota: Bibliotecas de análise mais sofisticadas podem indicar e/ou recuperar-se de erros na string de entrada.
  • 168. 168 Expressões aritméticas ● Considerando uma simples forma de expressões construídas a partir de dígitos únicos usando operações de adição + e multiplicação *, juntas com parênteses. ● Assumindo também que: – * e + associados a direita; – * tem prioridade maior do que +.
  • 169. 169 Expressões aritméticas (2) ● Formalmente, a sintaxe de tais expressões é definida pela seguinte gramática livre de contexto: exp → term '+' expr | term term → factor '*' term | factor factor → digit | '(' expr ')' digit → '0' | '1' | … | '9'
  • 170. 170 Expressões aritméticas (2) ● No entanto, por razões de eficiência, é importante fatorizar as regras para expr e term. exp → term ('+' expr | ε) term → term ('*' term | ε) Nota: O símbolo ε denota uma string vazia. Nota: O símbolo ε denota uma string vazia.
  • 171. 171 Expressões aritméticas (2) ● Agora é fácil traduzir a gramática em um analisador que avalia expressões, simplesmente reescrevendo as regras da gramática utilizando as primitivas de análise. expr :: Parser Int expr = do t <- term do char '+' e <- expr return (t + e) +++ return t
  • 172. 172 Expressões aritméticas (3) term :: Parser Int term = do f <- factor do char '*' t <- term return (f * t) +++ return f factor :: Parser Int factor = do d <- digit return (digitToInt d) +++ do char '(' e <- expr char ')' return e
  • 173. 173 Expressões aritméticas (4) ● Finalmente, definido: eval :: String -> Int eval xs = fst (head (parse expr xs)) ● E testando alguns exemplos: > eval "2*3+4" 10 > eval "2*(3+4)" 14
  • 175. 175 Introdução ● Até agora vimos como Haskell pode ser usado para escrever programas em lote que tomam todas as suas entradas no início e retornam todas as suas saídas no final. programa em lote programa em lote entradas saídas
  • 176. 176 teclado programa interativo entradas saídas tela Introdução (2) ● No entanto, também gostaríamos de usar Haskell para escrever programas interativos que leem a partir de um teclado e escrevem na tela, enquanto estiverem em execução.
  • 177. 177 O problema ● Programas em Haskell são funções matemáticas puras: – Programas em Haskell não têm efeitos colaterais. ● No entanto, ler de um teclado e escrever em uma tela são efeitos colaterais: – Programas interativos tem efeitos colaterais.
  • 178. 178 A solução ● Programas interativos podem ser escritos em Haskell usando tipos para distinguir expressões puras de ações impuras que podem envolver efeitos colaterais. IIOO aa Os tipos de ações que retornam um valor do tipo a. Os tipos de ações que retornam um valor do tipo a.
  • 179. 179 Por exemplo IIOO CChhaarr IIOO (()) O tipo de ações que retornam um caractere. O tipo de ações que retornam um caractere. O tipo de ações puramente com efeitos colaterais que não retornam nenhum O tipo de ações puramente com efeitos colaterais que não retornam nenhum valor. valor. Nota: () é um tipo de tupla sem componentes. Nota: () é um tipo de tupla sem componentes.
  • 180. – A ação getChar lê um caractere do teclado, ecoa na tela, e retorna o caractere como seu valor de resultado. 180 Ações básicas ● A biblioteca padrão fornece várias ações incluindo as seguintes ações primitivas: getChar :: IO Char
  • 181. 181 Ações básicas (2) ● A ação putChar c escreve o caractere c na tela, e não retorna nenhum valor como resultado: putChar :: Char -> IO () ● A ação return v simplesmente retorna o valor v, sem realizar nenhuma interação: return :: a -> IO a
  • 182. 182 Sequenciamento ● Uma sequência de ações podem ser combinadas como uma única ação composta usando a palavra do. a :: IO (Char,Char) a = do x <- getChar getChar Y <- getChar return (x,y) ● Por exemplo:
  • 183. 183 getLine :: IO String getLine = do x <- getChar if x == 'n' then return [] else do xs <- getLine return (x:xs) Primitivas derivadas ● Lendo uma string a partir do teclado:
  • 184. 184 putStr :: String -> IO () putStr [] = return () putStr (x:xs) = do putChar x putStr xs putStrLn :: String -> IO () putStrLn xs = do putStr xs putChar 'n' Primitivas derivadas(2) ● Escrevendo uma string na tela: ● Escrevendo uma string e movendo para uma nova linha:
  • 185. 185 strlen :: IO () strlen = do putStr "Enter a string: " Xs <- getLine putStr "The string has " putStr (show (length xs)) putStrLn " characters" Exemplo ● Agora é possível definir uma ação que espera uma string ser entrada e mostra seu comprimento:
  • 186. 186 Exemplo (2) > strlen Enter a string: abcde The string has 5 characters Nota: Avaliar uma ação executa seus efeitos colaterais, com seu valor final de resultado sendo descartado. Nota: Avaliar uma ação executa seus efeitos colaterais, com seu valor final de resultado sendo descartado.
  • 187. 187 Jogo da forca ● Considere a seguinte versão do jogo da forca: – Um jogador digita uma palavra secretamente; – O outro jogador tenta deduzir a palavra, entrando uma sequência de “chutes”; – Para cada “chute”, o computador indica quais letras da palavra secreta ocorrem no “chute”; – O jogo acaba quando o “chute” estiver correto.
  • 188. 188 Jogo da forca (2) ● Foi adotado a abordagem top-down para implementar o jogo da forca em Haskell, iniciando como se segue: hangman :: IO () hangman = do putStrLn "Think of a word: " Word <- sgetLine putStrLn "Try to guess it:" guess word
  • 189. 189 sgetLine :: IO String sgetLine = do x <- getCh if x == 'n' then do putChar x return [] else do putChar '-' Xs <- sgetLine return (x:xs) Jogo da forca (3) ● A ação sgetLine lê um linha de texto do teclado, ecoando cada caractere como um traço -:
  • 190. 190 import System.IO getCh :: IO Char getCh = do hSetEcho stdin False C <- getChar hSetEcho stdin True return c Jogo da forca (4) ● A ação getCh lê um único caractere do teclado, sem ecoar para a tela:
  • 191. 191 guess :: String -> IO () guess word = do putStr "> " Xs <- getLine if xs == word then putStrLn "You got it!" else do putStrLn (diff word xs) guess word Jogo da forca (5) ● A função guess é o loop principal, que requisita e processa os “chutes” até o jogo terminar:
  • 192. Jogo da forca (6) ● A função diff indica quais caracteres de uma string ocorrem na segunda string: [if elem x ys then x else '-' | x <- xs] 192 diff :: String -> String -> String diff xs ys = ● Por exemplo: > diff "haskell" "pascal" "-as--ll"
  • 193. Dica: Represente o tabuleiro como uma lista de cinco inteiros que representam o número de asteriscos remanescentes em cada linha. Por exemplo, o tabuleiro inicial é: [5,4,3,2,1]. 193 1: * * * * * 2: * * * * 3: * * * 4: * * 5: * Exercício ● Implemente o jogo nim em Haskell – Regras: ● O tabuleiro é composto de 5 linhas de asteriscos; ● Dois jogadores revesam a remoção de um ou mais asteriscos do fim de uma única linha; ● O ganhador é o jogador que remover o último asterisco ou asteriscos do tabuleiro. Dica: Represente o tabuleiro como uma lista de cinco inteiros que representam o número de asteriscos remanescentes em cada linha. Por exemplo, o tabuleiro inicial é: [5,4,3,2,1].
  • 194. Capítulo 10 – Declarando tipos e classes
  • 195. Declarações de tipo ● Em Haskell, um novo nome para um tipo existente pode ser definido usando uma declaração de tipo. type String = [Char] String String éé uumm ssiinnôônniimmoo ddee ttiippoo [[CChhaarr]]..
  • 196. Declarações de tipo (2) ● Declarações de tipo podem ser usadas para tornar outros tipos mais simples de ler. Por exemplo, dado type Pos = (Int,Int) ● Pode-se definir: origin :: Pos origin = (0,0) left :: Pos -> Pos left (x,y) = (x-1,y)
  • 197. Declarações de tipo (3) ● Como definições de funções, declarações de tipo também podem conter parâmetros. Por exemplo, dado type Pair a = (a,a) ● Pode-se definir: mult :: Pair Int -> Int mult (m,n) = m*n copy :: a -> Pair a copy x = (x,x)
  • 198. Declarações de tipo (3) ● Declarações de tipo podem ser aninhadas: type Pos = (Int,Int) type Trans = Pos -> Pos ● No entando, não podem ser recursivas: type Tree = (Int,[Tree])
  • 199. 199 Declarações de dados ● Um tipo completamente novo pode ser definido especificando seus valores uma uma declaração de dados. data Bool = False | True Bool é um novo tipo, com dois novos valores False e True. Bool é um novo tipo, com dois novos valores False e True.
  • 200. Declarações de dados (2) ● Nota: – Os dois valores False e True podem ser chamados de construtores do tipo Bool; – Nomes de tipos e construtores devem iniciar com letra maiúscula; – Declarações de dados são similares à gramáticas livres de contexto. O primeiro especifica os valores do tipo, e o último as sentenças da linguagem.
  • 201. Declarações de dados (3) ● Valores de novos tipos podem ser usados da mesma forma dos tipos nativos. Por exemplo, dado data Answer = Yes | No | Unknown ● Pode-se definir: answers :: [Answer] answers = [Yes,No,Unknown] flip :: Answer -> Answer flip Yes = No flip No = Yes flip Unknown = Unknown
  • 202. Declarações de dados (4) ● Os construtores um uma declaração de dados também podem possuir parâmetros. Por exemplo, dado data Shape = Circle Float ● Pode-se definir: | Rect Float Float square :: Float -> Shape square n = Rect n n area :: Shape -> Float area (Circle r) = pi * r^2 area (Rect x y) = x * y
  • 203. Declarações de dados (5) ● Nota: – Shape possui valores da forma Circle r onde r é float, e Rect x y onde x e y são floats. – Circle e Rect podem ser vistos como funções que constroem valores do tipo Shape: Circle :: Float -> Shape Rect :: Float -> Float -> Shape
  • 204. Declarações de dados (6) ● Sem surpresas, as próprias declarações de dados podem conter parâmetros. Por exemplo, dado data Maybe a = Nothing | Just a ● Pode-se definir: safediv :: Int -> Int -> Maybe Int safediv _ 0 = Nothing safediv m n = Just (m `div` n) safehead :: [a] -> Maybe a safehead [] = Nothing safehead xs = Just (head xs)
  • 205. 205 Referências ● Meijer, Erik. C9 Lectures: Functional Programming Fundamentals. Disponível em: <http://channel9.msdn.com/Series/C9-Lectures-Erik- Meijer-Functional-Programming-Fundamentals/Lecture- Series-Erik-Meijer-Functional-Programming- Fundamentals-Chapter-1>

Notas do Editor

  1. n = a `div` length xs where a = 10 xs = [1,2,3,4,5]