Você está na página 1de 31

Programação Funcional em

Haskell
Adalberto Cajueiro
Contexto

𝜆
• Qual o diferencial de linguagens funcionais?
𝜆
𝜆
• Raciocínio Sequencial x Funcional
• Haskell x Programação Funcional em Haskell
• Como lidar com a complexidade de programas?

𝜆
• Como reduzir tempo e custos?
• Como aumentar a confiabilidade e corretude?
Linguagens de programação funcional
• Clareza
𝜆 𝜆
𝜆
• Concisão
• Nível de abstração
• Suporte a reusabilidade

𝜆
• Aproximação de verificação formal (baseada em lambda calculus)
• Rápida prototipação
• Linguagem é apenas o veículo!!
Programação funcional

𝜆 𝜆
• É apenas um estilo que permite usar conceitos matemáticos de

𝜆
design e paradigma
• Statements x Expressions

𝜆
int total = 0;
for (int i = 1; i <= 10; i++){ sum [1..10]
total = total + i;
}
Histórico
• 1930s:
• Alonzo Church (Lambda Calculus)
𝜆 𝜆
𝜆
• 1950s:
• John MacCarthy (Lisp)
• 1960s:

𝜆
• Peter Ladin (ISWIM – If You See What I Mean)
• 1970s:
• John Backus (FP, high-order functions)
• Robert Milner (ML, inferência de tipo e tipos polimórficos-list T)
• 1970s – 1980s:
• David Turner (Miranda, lazy function)
Historico
• 1987:
𝜆 𝜆
𝜆
• Haskell (Lambda Calculus)
• 2003:
• Haskell 98 report
• Haskell Platform

rev [] = []
rev (x:xs) = rev xs ++ [x]

count [] = 0
count (x:xs) = 1 + count xs 𝜆
f [] = []
f (x:xs) = f ys ++ [x] ++ f zs
where
ys = [a | a <- xs, a <= x]
zs = [b | b <- ys, b > x]

factorial n = product [1..n]


Haskell
• Puramente funcional
• O que x Como
𝜆 𝜆
𝜆
• Livre de efeitos colaterais (variáveis imutáveis)
• Construções maiores pela colagem de funções menores
• Lazy
• Execução de funções sob demanda (avaliação estrita x não-estrita).

𝜆
• Ex: 2 <= 0 || null "abcd"
• Ex: fst (a,b) = a e snd (a,b) = b. O que acontece se usarmos b = head []?
• Estaticamente e fortemente tipada
• Possui inferência de tipos
• Elegante e concisa
• Conceitos de alto nível
Haskell
• Polimorfismo
𝜆 𝜆
𝜆
• Modularidade
• Performance (otimizações)
• Forte uso de pattern matching

𝜆
• Suporte a compilação e interpretação
• Porque Haskell não está no “mainstream”?
• Compatibilidade entre aplicações e linguagem nativa do SO
• Linguagens de programação não são pensadas como ferramentas
• Tecnologias x Formas de pensar
• Comodidade ou atendimento (bad design) às necessidades
Primeiros Passos

𝜆
• Evitar a memoria de músculos (ir direto à programação)
𝜆
𝜆
• Glasgow Haskell Compiler (GHC)
• http://haskell.org/platform

𝜆
Haskell scripts
• file.hs
𝜆 𝜆
𝜆
• Uso do editor de textos e ghci simultaneamente
• Regras de layout
• Tabulações x espaços. Melhor usar espaço. Similar a Python

𝜆
Ambientes para Haskell
• Haskell Platform
𝜆 𝜆
𝜆
• Comandos básicos (ghc, ghci)
• Instruções de instalação e uso
• Possibilidade de uso online
• Leksah: http://leksah.org/

𝜆
• EclipseFP: http://eclipsefp.github.io (descontinuado)
• Atom: https://atom-haskell.github.io/
Acesso à documentação

𝜆 𝜆
𝜆
𝜆
Primeiros passos
• Criação de um arquivo (texto) .hs
𝜆 𝜆
𝜆
• Uso do interpretador: ghci
• Escrita e execução de códigos

𝜆
Haskell Básico

𝜆
• Operações disponíveis: +, -, *, /, mod, sqrt
𝜆
𝜆
• Operadores lógicos:
• &&, ||, not
• Operadores relacionais

𝜆
• >,<,>=,<=,==,/=
• Pares
• (a,b)
• fst
• snd
Haskell Básico
• Declarando valores
𝜆 𝜆
𝜆
• x = expression.
• x=4
• x = []
• Expressões condicionais

𝜆
• abs n = if n >= 0 then n else –n
• Equações guardadas
• abs n | n >= 0 = n
| otherwise = -n
Funções em Haskell

𝜆
• Funções são o elemento mais importante de Haskell
𝜆
𝜆
• Baseadas no Lambda Calculus como teoria sobrejacente
• São consideradas funções de alta ordem
• Podem ser passadas como parâmetro ou retornar funções

𝜆
• Uso constante de recursão e pattern matching
Aplicação de Função Funções devem começar com

𝜆
letras minúsculas

Matemática Haskell 𝜆
𝜆 f(x)
f(x,y)
fx
f x y = (f x) g = x ‘f’ y

𝜆
f(g(x)) f (g x)
f(x,g(y)) f x (g y)
f(x)g(y) fx*gy
f(a,b) + c d f a b + c*d
f a + b = (f a) + b != f (a + b)
Introdução a listas

𝜆 𝜆
• Estruturas mais utilizadas em Haskell para diversos tipos de problemas

𝜆
• Estrutura de dados homogênea
• Ex:
• [2,4,6,8,10]
• [‘h’,’e’,’l’,’l’,’o’] = “hello”

𝜆
• Definição
• List = []
• List = head:List
• Ex:
• []
• [1,2,3]=1:[2,3] = 1:(2:[3]) = 1:(2:(3:[]))
Introdução a Listas
• Operadores
𝜆 𝜆
𝜆
• : (cons)
• ++ (concatenação)
• !! (seleção – listas são indexadas de 0 até m-1)
• >,<,>=,<= (comparação – compara a partir do primeiro elemento)

*Main> 3:[5,1]
[3,5,1]
*Main> 4:[]
[4]
*Main> []++[2]
[2]
[]

𝜆
*Main> []++[]

*Main> 4:[] ++ 2:[3]


[4,2,3]
*Main> [4,2,3] !! 0
4
*Main>
Introdução a Listas
• Funções (algumas são parciais)
𝜆 𝜆
𝜆
• head (cabeça – primeiro elemento)
• tail (cauda – lista sem a cabeça)
• last (último – último elemento)
• init (início – lista sem o último elemento)

𝜆
Introdução a Listas
• Funções
𝜆 𝜆
𝜆
• length (tamanho)
• null (testa se a lista é vazia)
• reverse (inverte a lista)
• take k (produz uma sublista do inicio até o elemento da k-esima posicao)

𝜆
drop k (produz uma sublista da k-esima posição ate o final)
• maximum
• minimum
• sum (soma os elementos de uma lista de números)
• product (multiplica os elementos de uma lista de números)
• elem (testa se um elemento pertence a uma lista)
Introdução a Listas
• Funções
𝜆 𝜆
𝜆
• [k..m] (range – produz uma lista de k até m)
• [0..5] = [0,1,2,3,4,5]
• [k,p..m] (range – produz uma lista de k até m seguindo a sequencia
estabelecida por k,p)

𝜆
• [0,2..8] = [0,2,4,6,8]
• [k..] (range - produz uma lista infinita)
• cycle (circulariza uma lista em uma lista infinita)
• cycle [1,2,3] = [1,2,3,1,2,3,1,2,3,...]
• repeat (pega um elemento e produz uma lista infinita com ele)
• replicate k n (produz uma lista com tamanho k contendo o elemento n]
Introdução a Listas
• Compreensão
𝜆 𝜆
ghci> [ x | x <- [10..20], x /= 13, x /= 15, x /= 19]
[10,11,12,14,16,17,18,20]

𝜆
• 2𝑥 𝑥 ∈ ℕ, 𝑥 ≤ 10}
ghci> [ x*y | x <- [2,5,10], y <- [8,10,11]]
• [2*x | x <- [0..10]] [16,20,22,40,50,55,80,100,110]
• [2*x | x <- [0..10],2*x > 12]
ghci> [ x*y | x <- [2,5,10], y <- [8,10,11], x*y > 50]
[55,80,100,110]

ghci> nouns = ["hobo","frog","pope"]


ghci> adjectives = ["lazy","grouchy","scheming"]

𝜆
ghci> [adjective ++ " " ++ noun | adjective <- adjectives, noun <- nouns]
["lazy hobo","lazy frog","lazy pope","grouchy hobo","grouchy frog",
"grouchy pope","scheming hobo","scheming frog","scheming pope"]

length' xs = sum [1 | _ <- xs]


Introdução a Listas

𝜆
removeNonUppercase st = [ c | c <- st, c `elem` ['A'..'Z']]
𝜆
𝜆ghci> removeNonUppercase "Hahaha! Ahahaha!"
"HA"
ghci> removeNonUppercase "IdontLIKEFROGS"
"ILIKEFROGS"

ghci> [ [ x | x <- xs, even x ] | xs <- xxs]


[[2,2,4],[2,4,6,8],[2,4,2,6,2,6]]

𝜆
ghci> xxs = [[1,3,5,2,3,1,2,4,5],[1,2,3,4,5,6,7,8,9],[1,2,4,2,1,6,3,1,3,2,3,6]]
Introdução a Listas
• Funções sobre listas
𝜆 𝜆
• map (recebe uma função e uma lista e aplica a função a todos os elementos da lista)

𝜆 • square x = x*x
• map square [0,1,2,3,4,5] = [0,1,4,9,16,25]
• filter (recebe um predicado e um a lista e retorna uma outra lista de elementos
satisfazendo o predicado)

𝜆
• filter even [0,1,2,3,4,5] = [0,2,4]
• foldr (recebe três argumentos: uma função, um valor inicial e uma lista. Substitui o
operador cons : pela função e a lista vazia com o valor inicial. Por exemplo,
considerar a lista [3,8,12,5], a função + e o valor inicial 0)
• foldr (+) 0 [3,8,12,5]
• 3:8:12:5:[]
*Main> foldr (*) 1 [4,8,5]
• 3+8+12+5+0
160
• 28
Introdução a Listas
• Funções
𝜆 𝜆
𝜆
• Associatividade em foldr (o que acontece quando o operador não é
associativo?)
• foldr assume que o operador é associativo à direita

foldr (-) 1 [4,8,5]

𝜆
==> 4 - (foldr (-) 1 [8,5])
==> 4 - (8 - foldr (-) 1 [5])
==> 4 - (8 - (5 - foldr (-) 1 []))
==> 4 - (8 - (5 - 1))
==> 4 - (8 - 4)
==> 4 - 4
==> 0
Introdução a Listas
• Funções
𝜆 𝜆
𝜆
• foldl (verão do foldr associando à esquerda)
foldl (+) 0 [3,8,12,5] = 28
foldl (-) 1 [4,8,5]
==> foldl (-) (1 - 4) [8,5]
==> foldl (-) ((1 - 4) - 8) [5]

𝜆
==> foldl (-) (((1 - 4) - 8) - 5) []
==> ((1 - 4) - 8) - 5
==> ((-3) - 8) - 5
==> (-11) - 5
==> -16

• foldl é frequentemente mais eficiente do que foldr


• foldr pode trabalhar em listas infinitas enquando foldl não pode.
Introdução a Listas
• Funções
𝜆 𝜆
𝜆
• foldl (verão do foldr associando à esquerda)
foldl (+) 0 [3,8,12,5] = 28
foldl (-) 1 [4,8,5]
==> foldl
foldr (-) para
expande (1 - f(x1,
4) [8,5]
f(x2, f(x3, f( ... )))). Assim.
==> foldl (-) ((1 - 4) - 8) [5]

𝜆
==> foldl
foldr (&&)(-) (((1
False - 4) -False)
(repeat 8) - 5) []
==> ((1False
produz - 4) &&
- 8) - 5 && (False && .... (False && *False*)) ... )
(False
==> ((-3) - 8) - 5
==> (-11)
foldl - 5 para f(f(f(f( ... ) xn-3) xn-2) xn-1)
expande
==> -16
foldl (&&) False (repeat False)
produz && (... (&& (&& *False* False) False) ...) False
• foldl é frequentemente mais eficiente do que foldr
• foldr pode trabalhar em listas infinitas enquando foldl não pode.
Tuplas

𝜆 𝜆
• São como listas, mas possuem um propósito de agrupar diversos

𝜆
dados em um só
• Não são homogêneas (permite combinar diversos tipos)
• Ex:

𝜆
• (2,5)
• (7.3,”hello”)
• (128312874-38,”Jose da Silva”,(Campina Grande,PB))
• Tuplas são comparadas componente a componente
Tuplas

𝜆
• Funções sobre pares (tupla com dois elementos)
𝜆
ghci> fst (8,11)

𝜆
• fst – retorna o primeiro elemento de um par 8
ghci> snd (8,11)
• snd – retorna o segundo elemento de um par 11

• Mais funções
• zip - junta duas listas em uma lista de pares
ghci> zip [1,2,3,4,5] [5,5,5,5,5]
[(1,5),(2,5),(3,5),(4,5),(5,5)]

𝜆
ghci> zip [5,3,2,6,2,7,2,5,4,6,6] ["im","a","turtle"]
[(5,"im"),(3,"a"),(2,"turtle")]

ghci> zip [1..] ["apple", "orange", "cherry", "mango"]


[(1,"apple"),(2,"orange"),(3,"cherry"),(4,"mango")]
Tuplas
• Quais triângulos-retângulos com perímetro igual a
𝜆 𝜆
𝜆
24 e lados menor que 10 (design por partes)
ghci> triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]
Gera todas as combinações possíveis sem filtro algum

𝜆
ghci> rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b],
a^2 + b^2 == c^2]
Lado b menor que hipotenusa (c) e lado a menor que lado b, e satisfazendo o teorema de Pitágoras
ghci> rightTriangles' = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b],
a^2 + b^2 == c^2, a+b+c == 24]
Filtro para considerar apenas os triângulos cuja soma dos lados é 24
ghci> rightTriangles'
[(6,8,10)]

Você também pode gostar