Paradigma Funcional
Caso de Estudo:
Haskell
Sobre mim
Sérgio Souza Costa
Professor - UFMA
Doutor em Computação Aplicada (INPE)
prof.sergio.costa@gmail.com
https://sit...
John McCarthy
(Boston, 4 de setembro de 1927 — 23 de outubro de 2011)
Criador da linguagem Lisp, segunda linguagem de prog...
Life is too short for imperative
programming
John Hughes
“ “
Paradigma Funcional
Linguagens onde as variáveis não mudam de valor durante a
execução. São imutáveis.
PARADIGMAS DE PROGRAMAÇÃO
É difícil programar em linguagem
funcional ?
Abra a cabeça
POO Vs Funcional
Programação orientada a objetos é um estilo de Programação
que permite:
● Reuso de código (via classes)
●...
POO Vs Funcional
Programação funcional é um estilo de programação
que permite:
- Reuso de código (composição de função)
- ...
Vantagens
● Códigos sucintos e concisos
○ Menor tempo de desenvolvimento
○ Manutenabilidade
● Códigos seguros
● Reusabilid...
Exemplo - Quick sort (Haskell)
qs [] = []
qs (x:xs) = qs [y | y <- xs, y < x]
++ [x]
++ qs [y | y <- xs, y >= x]
Exemplo - Quick sort (C)
int particao(int vec[], int inicio, int
fim) {
int i, j;
i = inicio;
for (j = inicio + 1; j <= fi...
Exemplo - Quick sort (C)
void quickSort(int vec[], int inicio,
int fim)
{
int p;
if (fim > inicio) {
p = particao(vec, ini...
Desvantagens
O computador não é funcional
● Maior custo de processamento
● Maior consumo de memória
Conceitos chaves
● Expressões
● Funções
● Polimorfismo paramétrico
E em algumas linguagens:
● Abstração de dados
● Avaliaç...
Conceitos chaves
● Expressão é um conceito chave, pois seu propósito é
computar novos valores a partir de valores antigos,...
Conceitos chaves
Abstração de dados é o conceito chave nas linguagens funcionais modernas, tais
como ML e HASKELL. Permite...
Caso de Estudo: Haskell
Haskell: Uma abordagem prática:
Real World Haskell
●http://book.realworldhaskell.org/read/
Haskell
● Uma linguagem puramente funcional
● Funções puras
● Funções são valores de primeira ordem
● Linguagem com divers...
http://www.haskell.org/haskellwiki/Haskell_in_industry
Haskell na Indústria
Elementos básicos
● Expressões e funções
● Tipos e valores
● Tuplas
● Listas
Expressões
●
Em Haskell, construímos expressões a partir de:
● literais
● operadores e parentese
● aplicação de funções
Expressões
● Literais:
-3.459
True
'a'
"hello"
[1,2,4,9]
● Aplicação de funções:
even 47
twice (-2)
Operadores
. Composição de funções
*, /, ^ multip, divisão, potência
+ , - adição, subtração
:, ++ composição de listas, c...
Estratégia call-by-value --- Avalia primeiro o
argumento antes de aplicar a função
(Pascal, C, Java, etc).
Estratégia call...
Tipos em Haskell
O que é um tipo?
Tipo é um conjunto de valores que possuem um comportamento uniforme
sobre dadas operaçõe...
Tipos em Haskell
Tipo é uma restrição
Descreve os limites do resultado final de uma computação
“The fundamental purpose of...
Tipos primitivos
●Bool Boleanos
●Char Caracteres
●Int Inteiros de 32-bits
●Integer Inteiros de tam ilimitado
●Float Ponto ...
Toda expressão tem um tipo
Os tipos podem ser inferidos
Prelude> :t (4 > 5)
(4 > 5) :: Bool
Prelude> :t (5+4)
(5+4) :: (Nu...
Função
● Correspondência biunívoca de membros do conjunto domínio para membros
do conjunto imagem
● Ordem de avaliação de ...
Função
● Nome lista de parâmetros = expressão de correspondência
○ cubo x = x * x * x
● Um elemento do conjunto imagem é o...
f1 :: Int → Int → Int
f1 x y = x*y
Função
● A definição de uma função deve obedecer a sintaxe seguinte:
nome_função :: tip...
Matemática
f (x)
f (x,y)
f (g(x))
f (x, g(y))
f (x) g(y)
f(a,b) + c d
Haskell
f x
f x y
f (g x) ou f $ g x
f x (g y) ou f ...
Funções como valores de primeira classe
Significa que as funções têm um estatuto tão importante como o dos inteiros, reais...
Expressão de seleção (ou condicional)
menor x y =
se x <= y então o resultado da expressão é x
senão o resultado é y
Consi...
Expressão de seleção
if <condição> then <resultado 1>
else <resultado2>
menor :: Int -> Int -> Int
menor x y = if x <= y t...
-- fatorial
fat :: Integer -> Integer
fat 0 = 1
fat n = fat (n-1) * n
Casamento de padrões
Podemos especificar o comportam...
Listas
● Uma lista é uma sequência de valores ordenados
● Listas são homogêneas:
●todos os elementos da lista tem o mesmo ...
Listas
Uma lista é composta sempre de dois segmentos: cabeça
(head) e corpo (tail). A cabeça é sempre o primeiro emento e
...
Listas em Haskell
●
● Três tipos de notação:
● construtores:
1 : 1 : 2 : 3 : 5 : 8 : []
● “colchetes":
[1, 1, 2, 3, 5, 8]
...
Listas
Pode se definir uma lista indicando os limites inferior e superior:
[<limite-inferior> .. <limite-superior>]
Listas
Podemos definir qualquer progressão aritmética em uma lista utilizando a
seguinte notação:
[<termo1>, <termo2> .. <...
Listas por compreensão
A definição de listas por compreensão é feita por um construtor de listas
que utiliza conceitos e n...
Compreensão de listas
● Um construtor de processamento de listas em linguagem de programação, a
notação matemática é a seg...
Exemplo:
[x | x <- [1..1000], even x, x < 100 ]
[2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,
46,48,50,5...
Listas com mais um gerador
Compreensão de listas
isempty :: [a] -> Bool
isempty [] = True
isempty anythingElse = False
length [] = 0
length (x : xs) = 1 + length xs
head [...
Recursão
length :: [a] -> Int
length [] = 0
length (x : xs) = 1 + length xs
Um conceito básico em Haskell é o uso de recur...
Recursão
● Sem loops explícitos, o fluxo em Haskell é usualmente expresso por recursão.
● Como garantir que recursão termi...
Recursão
●
A soma dos números de uma lista vazia
sumAll (x : xs) = x + sumAll xs
sumAll [] = 0
sumAll :: [Integer] -> Inte...
Recursão
●
Concatenar uma lista vazia:
concat (s : ss) = s ++ concat ss
concat [] = [] --- = “”
concat :: [[Char]] -> [Cha...
Avaliação de Funções Recursivas
length [] = 0
length (x : xs) = 1 + (length xs)
length (1 : 2 : 4 : [])
1 + length (2 : 4 ...
Recursos avançados
●
1. Definições locais,
2. Importando bibliotecas externas,
3. Funções de segunda ordem
4. Trabalhando ...
Definições locais
raizes (a, b, c) = (x1,x2)
where
delta = sqrt ( b^2 - 4*a*c)
x1 = ((-b) + delta) / (2*a)
x2 = ((-b) - de...
Sinônimos
type Point = (Int, Int)
type Polygon = [Point]
p1 :: Point
p1 = (1,4)
pol1:: Polygon
pol1 = [(1,1),(1,2),(3,1),(...
Avaliação parcial
57
Haskell distingue entre operadores and funções:
Operadores têm noção infixa (e.g. 1 + 2),
Funções usa...
Avaliação parcial
multThree :: (Num a) => a -> a -> a -> a
multThree x y z = x * y * z
ghci> let multTwoWithNine = multThr...
Avaliação parcial
divideByTen :: (Floating a) => a -> a
divideByTen = (/10)
59
A função divideByTen 200 é equivalente a 20...
Funções são valores de primeira classe
60
● Em linguagens funcionais, funções são valores de primeira classe.
● Não existe...
Funções como argumentos
twice :: (a -> a) -> a -> a
twice f x = f (f x)
61
Uma característica poderosa de Haskell é funçõe...
Map
map :: (a -> b) -> [a] -> [b]
Main> map double [1,3,5,7]
[2,6,10,14]
62
A função map aplica uma função a todos os elem...
Map pode ser definido por recursão ou por compreensão de
listas
Ou por compreensão de lista
Map
map :: (a -> b) -> [a] -> ...
ghci> map (+3) [1,5,3,1,6]
[4,8,6,4,9]
ghci> map (++ "!") ["BIFF", "BANG", "POW"]
["BIFF!","BANG!","POW!"]
ghci> map (repl...
Map com avaliação parcial
Main> map (*5) [1,3,5,7]
[5,15,25,35]
incAll = map (1 +)
addNewlines = map (++ "n")
halveAll = m...
Filter
filter :: (a -> Bool) -> [a] -> [a]
Main> filter even [1..10]
[2,4,6,8,10]
66
A função filter seleciona os elemento...
Filter
filter :: (a -> Bool) -> [a] -> [a]
filter p xs = [x | x <- xs, p x]
filter p [] = []
filter p (x : xs)
| p x = x :...
Comprimindo para um único valor
f [] = v
f (x:xs) = x <- f xs
68
Um grande número de funções em listas podem ser definidas...
Comprimindo para um único valor
sum [] = 0
sum (x:xs) = x + sum xs
product [] = 1
product (x:xs) = x * product xs
and [] =...
Comprimindo para um único valor
sum = foldr (+) 0
product = foldr (*) 1
and = foldr (&&) True
70
A função foldr (“fold rig...
Definição do foldr
foldr::(a -> b -> b) -> b -> [a] -> b
foldr f v [] = v
foldr f v (x:xs) =
f x (foldr f v xs)
71
Composição de Funções
(f . g) x = f (g x)
> ( (*2) . (*5) ) 8
> 80
72
Abstração de dados
73
Tipos enumerados (enumerated no C),
Tipos cartesianos (struct no C),
Uniões disjunta (union no C)
Ti...
O que vimos até então...
type Matricula = Int
type Nome = String
type Salario = Double
type Funcionario = (Matricula, Nome...
Qual o problema com os sinônimos?
75
Qual o problema com os sinônimos?
76
type Matricula = Int
type Nome = String
type Salario = Double
type Funcionario = (Mat...
Usando tipos algébricos do Haskell
Data Funcionario = Funcionario Int String Double
type Matricula = Int
type Nome = Strin...
Tipos Compostos
78
Os tipos algébricos do Haskell permite estruturas diversos tipos a partir de valores
mais simples.
● Pr...
Tipos algébricos
data InfoLivro = Livro Int String [String]
Nome do tipo
Construtor de tipo
Diferenças entre nome de tipos...
Tipos algébricos
data Matricula = Matricula Int
deriving (Show, Ord, Eq)
Palavra chave
para derivar
classes
80
O Haskell d...
Tipos algébricos – Registro
struct Point {
x,y: double;
};
data Point = Pt Double Double
deriving (Show)
C
Haskell
81
Tipos algébricos – Registro
data Point = Pt Double Double
deriving (Show)
getX :: Point → Double
getx Pt x y = x
getY :: P...
Enumerandos
enum Dias {Segunda, Terça, Quarta,
Quinta, Sexta}
data Dias = Segunda | Terça | Quarta
| Quinta | Sexta derivi...
Tipo Booleano
data Booleano = Falso | Verdadeiro deriving (Show, Eq)
e :: Booleano -> Booleano -> Booleano
e Falso _ = Fal...
União Disjunta em Haskell
data Number = Exact Int | Inexact Float
Valores:
Number = Exact Integer + Inexact Float
… Exact(...
Exemplo de união disjunta
data Number = Exact Int | Inexact Float deriving (Show)
pi2 = Inexact 3.1416
rounded :: Number -...
União Disjunta – Tratando erro
data Maybe a = Nothing | Just a
87
Em Haskell existe um tipo de dado muito util em casos on...
União Disjunta
union {
int exact;
int inexact;
};
data Number = Exact Int |
Inexact Float
HaskellC
88
Tipos Recursivos
data Nat = Zero | Succ Nat
data Lista = Nil | Cons Int Lista
data ArvoreBin = Vazia |
Nodo Int ArvoreBin ...
Tipos Recursivos
Números naturais
data Nat = Zero | Succ Nat
Nat é um novo tipo com dois construtores
Zero :: Nat e Succ :...
Tipos recursivos
data Nat = Zero | Succ Nat deriving (Show)
soma :: Nat -> Nat -> Nat
soma Zero n = n
soma (Succ m) n = Su...
Tipos Recursivos - Lista
data List =
Nil |
Cons Int List
deriving (Show)
first (Cons a s) = a
first Nil = error "vazio"
re...
Polimorfismo Paramétrico
C++
template <typedef T>
T maior (T a, T b) {
return ( (a>b)? a : b );
}
public class Pair<T, S>{...
Polimorfismo paramétrico
94
● Funções paramétricas
● Tipos de dados paramétrico
● Uma característica importante de Haskell é o uso de tipos paramétricos
● Muitas funções podem ser definidas em termos de...
data List a =
Nil |
Cons a List
deriving (Show)
first :: List a → a
first (Cons a s) = a
first Nil = error "vazio"
rest ::...
data ArvBin a = Vazia | Nodo a (ArvBin a) (ArvBin a)
deriving Show
elem :: ArvBin a -> a
elem Vazia = error "arvore vazia"...
Definindo as funções de acesso
diretamente na definição
data ArvBin a = Vazia |
Nodo {
elem :: a,
esq :: (ArvBin a),
dir :...
Restrição no polimorfismo
somatodos :: [a] -> a
somatodos (x:xs) = x + somatodos xs
99
Esta função pode ser aplicada a qua...
Restrição no polimorfismo
somatodos :: (Num a) => [a] -> a
somatodos (x:xs) = x + somatodos xs
100
Usando “type classes
A ...
Type class em Haskell
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
101
●Uma classe é uma coleção de tipo...
Classes Básicas em Haskell
Eq - tipos com igualdade
Ord – tipos ordenados
Show – tipos que podem ser transformados em stri...
Instanciando type class
data Point = Point Int Int deriving (Show, Eq, Ord,
Read)
instance Num Point where
(+) (Point x1 y...
data Point = Point Int Int
instance Show Point where
show (Point x y) = show (x,y)
Prelude> Point 4 5
> (4,5)
104
Instanci...
Programas e
operações de
entrada e
saída
105
Operações de entrada e saída
106
Até então, vimos como usar o Haskell via ghci, mas como
gerar um programa compilável?
Com...
O problema ...
Um programa em
Haskell consiste
num conjunto de
funções, sem
efeitos colaterais
O objetivo de
executar qqer...
A solução
IO a
O tipo das ações de IO que retornam
um valor do tipo a
108
Escrever programas interativos em Haskell usando...
I/O em Haskell
IO Char
IO ()
O tipo das ações de IO que retornam
um caracter
O tipo das ações que não tem valor
de retorno...
IO em Haskell: O tipo (IO a)
Um valor do tipo (IO t) é uma ação que, quando realizada, pode
fazer alguma forma de IO antes...
Meu Primeiro Programa
Ou, compile em código nátivo.
module Main where
main = putStrLn "Hello World!"
runghc hello.hs
Hello...
Funções da biblioteca
112
Funções para escrever na tela
putStr :: String -> IO ()
putStrLn :: String -> IO ()
Para ler uma...
Combinando ações
Cada ação é nessa forma:
113
Para combinar ações podemos usar a notação “do”;
Meu segundo programa
module Main where
main = do
input <- getLine
putStrLn input
114
Lê uma entrada do usuário e imprime n...
Meu terceiro programa
module Main where
ask :: String -> IO String
ask question = do
putStrLn question
getLine
main :: IO ...
Trabalhando com arquivos
import IO
import Data.Char
main = do
str <- readFile "input.txt"
writeFile "output.txt" (map toUp...
Funções para string
117
Função lines, quebra uma string pelo marcador de fim de linha
lines “linha1nlinha2”
= [“linha1”,li...
Trabalhando com arquivos
main = do
str <- readFile "input.txt"
print (length (words str))
print (length (lines str))
118
FIM
Próximos SlideShares
Carregando em…5
×

Paradigma Funcional - Caso de Estudo Haskell

5.454 visualizações

Publicada em

Publicada em: Tecnologia
1 comentário
2 gostaram
Estatísticas
Notas
Sem downloads
Visualizações
Visualizações totais
5.454
No SlideShare
0
A partir de incorporações
0
Número de incorporações
1.309
Ações
Compartilhamentos
0
Downloads
159
Comentários
1
Gostaram
2
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Paradigma Funcional - Caso de Estudo Haskell

  1. 1. Paradigma Funcional Caso de Estudo: Haskell
  2. 2. Sobre mim Sérgio Souza Costa Professor - UFMA Doutor em Computação Aplicada (INPE) prof.sergio.costa@gmail.com https://sites.google.com/site/profsergiocosta/home https://twitter.com/profsergiocosta http://gplus.to/sergiosouzacosta http://www.slideshare.net/skosta/presentations?order=popular
  3. 3. John McCarthy (Boston, 4 de setembro de 1927 — 23 de outubro de 2011) Criador da linguagem Lisp, segunda linguagem de programação.
  4. 4. Life is too short for imperative programming John Hughes “ “
  5. 5. Paradigma Funcional Linguagens onde as variáveis não mudam de valor durante a execução. São imutáveis.
  6. 6. PARADIGMAS DE PROGRAMAÇÃO
  7. 7. É difícil programar em linguagem funcional ?
  8. 8. Abra a cabeça
  9. 9. POO Vs Funcional Programação orientada a objetos é um estilo de Programação que permite: ● Reuso de código (via classes) ● Eliminação de bugs (via encapsulamento, ocultação de dados )
  10. 10. POO Vs Funcional Programação funcional é um estilo de programação que permite: - Reuso de código (composição de função) - Eliminação de bug (via imutabilidade (não existe mudança de valores de variáveis))
  11. 11. Vantagens ● Códigos sucintos e concisos ○ Menor tempo de desenvolvimento ○ Manutenabilidade ● Códigos seguros ● Reusabilidade ● Facilidade de escrita, suporte a abstrações ● Confiabilidade, segurança
  12. 12. Exemplo - Quick sort (Haskell) qs [] = [] qs (x:xs) = qs [y | y <- xs, y < x] ++ [x] ++ qs [y | y <- xs, y >= x]
  13. 13. Exemplo - Quick sort (C) int particao(int vec[], int inicio, int fim) { int i, j; i = inicio; for (j = inicio + 1; j <= fim; ++j) { if (vec[j] < vec[inicio]) { ++i; troca(&vec[i], &vec[j]); } } troca(&vec[inicio], &vec[i]); return i; }
  14. 14. Exemplo - Quick sort (C) void quickSort(int vec[], int inicio, int fim) { int p; if (fim > inicio) { p = particao(vec, inicio, fim); quickSort(vec, inicio, p - 1); quickSort(vec, p + 1, fim); }
  15. 15. Desvantagens O computador não é funcional ● Maior custo de processamento ● Maior consumo de memória
  16. 16. Conceitos chaves ● Expressões ● Funções ● Polimorfismo paramétrico E em algumas linguagens: ● Abstração de dados ● Avaliação preguiçosa.
  17. 17. Conceitos chaves ● Expressão é um conceito chave, pois seu propósito é computar novos valores a partir de valores antigos, que é a essência da programação funcional. ● Função é um conceito chave, pois funções generalizam expressões. Além disso, funções são valores de primeira classe, dado que podem ser argumento e resultado de outras funções, fazer parte de valores compostos ..
  18. 18. Conceitos chaves Abstração de dados é o conceito chave nas linguagens funcionais modernas, tais como ML e HASKELL. Permitem criar novos tipos de dados a partir dos já existentes. Polimorfismo paramétrico é um conceito chave, pois ele permite que uma função opere sobre valores de uma família de tipos, ao invés de apenas um tipo. Na prática, muitas funções são naturalmente polimórficas, e o polimorfismo paramétrico incrementar o poder e a expressividade das linguagens funcionais Avaliação preguiçosa é baseada na noção que uma expressão só será avaliada se for usada.
  19. 19. Caso de Estudo: Haskell Haskell: Uma abordagem prática: Real World Haskell ●http://book.realworldhaskell.org/read/
  20. 20. Haskell ● Uma linguagem puramente funcional ● Funções puras ● Funções são valores de primeira ordem ● Linguagem com diversos recursos avançados: ● Casamento de padrões ● Compreensão de lista ● Avaliação preguiçosa ● Polimorfismo parametrico
  21. 21. http://www.haskell.org/haskellwiki/Haskell_in_industry Haskell na Indústria
  22. 22. Elementos básicos ● Expressões e funções ● Tipos e valores ● Tuplas ● Listas
  23. 23. Expressões ● Em Haskell, construímos expressões a partir de: ● literais ● operadores e parentese ● aplicação de funções
  24. 24. Expressões ● Literais: -3.459 True 'a' "hello" [1,2,4,9] ● Aplicação de funções: even 47 twice (-2)
  25. 25. Operadores . Composição de funções *, /, ^ multip, divisão, potência + , - adição, subtração :, ++ composição de listas, concatenação ==,/=,<=,... igual, desigual, comparação && E || OU
  26. 26. Estratégia call-by-value --- Avalia primeiro o argumento antes de aplicar a função (Pascal, C, Java, etc). Estratégia call-by-name (ou AVALIAÇÃO PREGUIÇOSA) --- Aplica imediatamente a função ao argumento, adiando para mais tarde a avaliação desse argumento (Haskell e Miranda) Estatégias de avaliação
  27. 27. Tipos em Haskell O que é um tipo? Tipo é um conjunto de valores que possuem um comportamento uniforme sobre dadas operações. (David Watt) “A program variable can assume a range of values during the execution of a program. An upper bound of such a range is called a type of the variable” (Cardelli)
  28. 28. Tipos em Haskell Tipo é uma restrição Descreve os limites do resultado final de uma computação “The fundamental purpose of a type system is to prevent the occurrence of execution errors during the running of a program” (Cardelli).
  29. 29. Tipos primitivos ●Bool Boleanos ●Char Caracteres ●Int Inteiros de 32-bits ●Integer Inteiros de tam ilimitado ●Float Ponto flutuante ●Double Dupla precisão
  30. 30. Toda expressão tem um tipo Os tipos podem ser inferidos Prelude> :t (4 > 5) (4 > 5) :: Bool Prelude> :t (5+4) (5+4) :: (Num t) => t Prelude> :t [1.2,5.0] [1.2,5.0] :: (Fractional t) => [t]
  31. 31. Função ● Correspondência biunívoca de membros do conjunto domínio para membros do conjunto imagem ● Ordem de avaliação de suas expressões é controlada por expressões condicionais ○ Não pela seqüência ou pela repetição iterativa ● Não têm efeitos colaterais ○ Sempre definem o mesmo valor dado o mesmo conjunto de argumentos, diferentemente de um procedimento em linguagens imperativas.
  32. 32. Função ● Nome lista de parâmetros = expressão de correspondência ○ cubo x = x * x * x ● Um elemento do conjunto imagem é obtido para cada par: Nome da função + um elemento particular do conjunto domínio ○ cubo 2.0 = 8.0 ● Definição de uma função separada da tarefa de nomeá-la ○ Notação lambda (Church, 1941) ○ λ(x) x * x * x
  33. 33. f1 :: Int → Int → Int f1 x y = x*y Função ● A definição de uma função deve obedecer a sintaxe seguinte: nome_função :: tipo_arg1 -> ... -> tipo_argN -> tipo_saída nome_função arg1 ... argN = <expressão_resultado> ● Sendo tipo1,...,tipoN os tipos dos parâmetros de entrada da função.
  34. 34. Matemática f (x) f (x,y) f (g(x)) f (x, g(y)) f (x) g(y) f(a,b) + c d Haskell f x f x y f (g x) ou f $ g x f x (g y) ou f $ g y f x * g y f a b + c * d Função
  35. 35. Funções como valores de primeira classe Significa que as funções têm um estatuto tão importante como o dos inteiros, reais, e outros tipos predefinidos. Concretamente, numa linguagem funcional as funções podem ... ● Ser passadas como argumento para outras funções; ● Podem ser retornadas por outras funções; ● Podem ser usadas como elementos constituintes de estruturas de dados; Prelude>map (x->2*x) [1,2,3] [2,4,6]
  36. 36. Expressão de seleção (ou condicional) menor x y = se x <= y então o resultado da expressão é x senão o resultado é y Considere uma função que dado dois valores, retorna o menor: A estratégia para resolução do problema é com uso de uma expressão de seleção
  37. 37. Expressão de seleção if <condição> then <resultado 1> else <resultado2> menor :: Int -> Int -> Int menor x y = if x <= y then x else y
  38. 38. -- fatorial fat :: Integer -> Integer fat 0 = 1 fat n = fat (n-1) * n Casamento de padrões Podemos especificar o comportamento de uma função descrevendo sua resposta a diferentes situações de entrada. ● Podemos ter múltiplas definições ● Alternativa aos “ifs”
  39. 39. Listas ● Uma lista é uma sequência de valores ordenados ● Listas são homogêneas: ●todos os elementos da lista tem o mesmo tipo ● Listas são dinâmicas: ●não há restrição no tamanho de listas (incluindo listas infinitas)
  40. 40. Listas Uma lista é composta sempre de dois segmentos: cabeça (head) e corpo (tail). A cabeça é sempre o primeiro emento e corpo é uma lista com os demais elementos. Prelude> ['a','b','c','d'] "abcd" Prelude> 'a':['b','c','d'] "abcd"
  41. 41. Listas em Haskell ● ● Três tipos de notação: ● construtores: 1 : 1 : 2 : 3 : 5 : 8 : [] ● “colchetes": [1, 1, 2, 3, 5, 8] ● strings (apenas para listas de caracteres): ['h', 'e', 'l', 'l', 'o'] = "hello"
  42. 42. Listas Pode se definir uma lista indicando os limites inferior e superior: [<limite-inferior> .. <limite-superior>]
  43. 43. Listas Podemos definir qualquer progressão aritmética em uma lista utilizando a seguinte notação: [<termo1>, <termo2> .. <limite-superior> Prelude> [0,3..21] [0,3,6,9,12,15,18,21] Prelude> [0,2..20] [0,2,4,6,8,10,12,14,16,18,20]
  44. 44. Listas por compreensão A definição de listas por compreensão é feita por um construtor de listas que utiliza conceitos e notações da teoria dos conjuntos. Assim, para um conjunto A temos: Sendo E(x) uma expressão em X, onde X pertence a lista, dados um conjunto de proposições Pi(x) A = [E(x) | x <- lista, P1(x), ..., Pn(x)] Por exemplo: [x | x <- l1, even x, x < 100 ], todos pares menos que 100 pertencentes a l1
  45. 45. Compreensão de listas ● Um construtor de processamento de listas em linguagem de programação, a notação matemática é a seguinte: ● Outros exemplos ● Por exemplo, as 10 primeiras potências de 2: [2 ^ x | x <- [1..10] ] ● Todos os números pares maiores que 1 e menores que 100: [ x | x <- [1..100] , par x ]
  46. 46. Exemplo: [x | x <- [1..1000], even x, x < 100 ] [2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44, 46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,8 4,86,88,90,92,94,96,98] Compreensão de listas
  47. 47. Listas com mais um gerador Compreensão de listas
  48. 48. isempty :: [a] -> Bool isempty [] = True isempty anythingElse = False length [] = 0 length (x : xs) = 1 + length xs head [] = error "head []" head (x:xs) = x Casamento de padrões (lista)
  49. 49. Recursão length :: [a] -> Int length [] = 0 length (x : xs) = 1 + length xs Um conceito básico em Haskell é o uso de recursão para definição de funções
  50. 50. Recursão ● Sem loops explícitos, o fluxo em Haskell é usualmente expresso por recursão. ● Como garantir que recursão termine? ○ Escolha uma “entidade” para focar o processo ○ Garanta que a próxima chamada estará mais próxima de uma condição de término Exemplos: ● Decrementar um valor para cada chamada ● Tomar um valor de uma lista a cada chamada
  51. 51. Recursão ● A soma dos números de uma lista vazia sumAll (x : xs) = x + sumAll xs sumAll [] = 0 sumAll :: [Integer] -> Integer Soma de todos os números de uma lista Soma dos números de uma lista x : xs
  52. 52. Recursão ● Concatenar uma lista vazia: concat (s : ss) = s ++ concat ss concat [] = [] --- = “” concat :: [[Char]] -> [Char] Concatenação de listas de caracteres Concatenar uma lista a partir de um elemento:
  53. 53. Avaliação de Funções Recursivas length [] = 0 length (x : xs) = 1 + (length xs) length (1 : 2 : 4 : []) 1 + length (2 : 4 : []) 1 + 1 + length (4 : []) 1 + 1 + 1 + length [] 1 + 1 + 1 + 0
  54. 54. Recursos avançados ● 1. Definições locais, 2. Importando bibliotecas externas, 3. Funções de segunda ordem 4. Trabalhando com entrada e saída 54
  55. 55. Definições locais raizes (a, b, c) = (x1,x2) where delta = sqrt ( b^2 - 4*a*c) x1 = ((-b) + delta) / (2*a) x2 = ((-b) - delta) / (2*a) 55 Para uma melhor legibilidade de um código, podemos usar a cláusula “where” para fazer definições visíveis somente por uma dada função.
  56. 56. Sinônimos type Point = (Int, Int) type Polygon = [Point] p1 :: Point p1 = (1,4) pol1:: Polygon pol1 = [(1,1),(1,2),(3,1),(1,1)] 56 Em Haskell, é possível criar sinônimos de tipos, ex:
  57. 57. Avaliação parcial 57 Haskell distingue entre operadores and funções: Operadores têm noção infixa (e.g. 1 + 2), Funções usam notação prefixa (e.g. plus 1 2). Operadores podem ser convertidos em funções colocando-os entre parênteses: (+) m n = m + n. Haskell aceita operadores com avaliação parcial. E.g.: (+ m) n = m + n (: 0) l = 0 : l
  58. 58. Avaliação parcial multThree :: (Num a) => a -> a -> a -> a multThree x y z = x * y * z ghci> let multTwoWithNine = multThree 9 ghci> multTwoWithNine 2 3 54 ghci> let multWithEighteen = multTwoWithNine 2 ghci> multWithEighteen 10 180 58
  59. 59. Avaliação parcial divideByTen :: (Floating a) => a -> a divideByTen = (/10) 59 A função divideByTen 200 é equivalente a 200 / 10, ou (/10) 200
  60. 60. Funções são valores de primeira classe 60 ● Em linguagens funcionais, funções são valores de primeira classe. ● Não existe restrição sobre o uso de funções em linguagens funcionais, ● Podem ser argumentos de funções ● Saídas de funções ● Elementos de estrutura de dados
  61. 61. Funções como argumentos twice :: (a -> a) -> a -> a twice f x = f (f x) 61 Uma característica poderosa de Haskell é funções podem ser argumentos de outras funções. Estas funções são chamadas funções de segunda ordem.
  62. 62. Map map :: (a -> b) -> [a] -> [b] Main> map double [1,3,5,7] [2,6,10,14] 62 A função map aplica uma função a todos os elementos de uma lista.
  63. 63. Map pode ser definido por recursão ou por compreensão de listas Ou por compreensão de lista Map map :: (a -> b) -> [a] -> [b] map f xs = [f x | x xs] map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x : xs) = (f x) : map f xs 63
  64. 64. ghci> map (+3) [1,5,3,1,6] [4,8,6,4,9] ghci> map (++ "!") ["BIFF", "BANG", "POW"] ["BIFF!","BANG!","POW!"] ghci> map (replicate 3) [3..6] [[3,3,3],[4,4,4],[5,5,5],[6,6,6]] ghci> map (map (^2)) [[1,2],[3,4,5,6],[7,8]] [[1,4],[9,16,25,36],[49,64]] ghci> map fst [(1,2),(3,5),(6,3),(2,6),(2,5)] [1,3,6,2,2] 64 Map
  65. 65. Map com avaliação parcial Main> map (*5) [1,3,5,7] [5,15,25,35] incAll = map (1 +) addNewlines = map (++ "n") halveAll = map (/2) squareAll = map (^2) stringify = map (: []) 65
  66. 66. Filter filter :: (a -> Bool) -> [a] -> [a] Main> filter even [1..10] [2,4,6,8,10] 66 A função filter seleciona os elementos de uma lista que satisfazem a um predicado
  67. 67. Filter filter :: (a -> Bool) -> [a] -> [a] filter p xs = [x | x <- xs, p x] filter p [] = [] filter p (x : xs) | p x = x : filter p xs | otherwise = filter p xs 67 Pode ser definido como compreensão de listas ou por recursão
  68. 68. Comprimindo para um único valor f [] = v f (x:xs) = x <- f xs 68 Um grande número de funções em listas podem ser definidas a partir de um padrão simples de recursão ●A lista vazia recebe para um valor final, e uma lista ●não vazia é mapeada para um operador : que ●combina o primeiro elemento com a aplicação da função no resto da lista
  69. 69. Comprimindo para um único valor sum [] = 0 sum (x:xs) = x + sum xs product [] = 1 product (x:xs) = x * product xs and [] = True and (x:xs) = x && and xs 11/4/11 69
  70. 70. Comprimindo para um único valor sum = foldr (+) 0 product = foldr (*) 1 and = foldr (&&) True 70 A função foldr (“fold right”) encapsula este padrão de recursão em listas, com a função dada e o valor v como argumentos
  71. 71. Definição do foldr foldr::(a -> b -> b) -> b -> [a] -> b foldr f v [] = v foldr f v (x:xs) = f x (foldr f v xs) 71
  72. 72. Composição de Funções (f . g) x = f (g x) > ( (*2) . (*5) ) 8 > 80 72
  73. 73. Abstração de dados 73 Tipos enumerados (enumerated no C), Tipos cartesianos (struct no C), Uniões disjunta (union no C) Tipos recursivos
  74. 74. O que vimos até então... type Matricula = Int type Nome = String type Salario = Double type Funcionario = (Matricula, Nome, Salario) 74 Usamos os tipos existentes em Haskell ● Primitivos: Int, String, Bool ● Compostos: Listas e tuplas Aprendemos criar sinônimos :
  75. 75. Qual o problema com os sinônimos? 75
  76. 76. Qual o problema com os sinônimos? 76 type Matricula = Int type Nome = String type Salario = Double type Funcionario = (Matricula, Nome, Salario) funcionarios :: [Funcionario] funcionarios = [(1235,"joao", 580), (256,"jose", 590)] aumentaSalario :: Funcionario -> Funcionario aumentaSalario (m,n,s) = (m,n,s+(0.1*s)) type Nota = Double type Alunos = (Matricula, Nome, Nota) alunos :: [Alunos] alunos = [(1,"antonio", 50.6), (6,"maria", 70)] – eu poderia aplicar aumentaSalario a um aluno, pois são a mesma tupla, – apenas com nomes diferentes
  77. 77. Usando tipos algébricos do Haskell Data Funcionario = Funcionario Int String Double type Matricula = Int type Nome = String type Salario = Double Data Funcionario = Funcionario Matricula Nome Salario Nós definimos um novo tipo de dado usando o palavra-chave data.
  78. 78. Tipos Compostos 78 Os tipos algébricos do Haskell permite estruturas diversos tipos a partir de valores mais simples. ● Produto cartesiano ( registros) ● Tipos enumerados ● Uniões disjuntas (variantes e uniões) ● Tipos recursivos (estruturas de dados dinâmicas)
  79. 79. Tipos algébricos data InfoLivro = Livro Int String [String] Nome do tipo Construtor de tipo Diferenças entre nome de tipos e construtor de tipos: O nome do tipo e dos construtores não precisa ser iguais.
  80. 80. Tipos algébricos data Matricula = Matricula Int deriving (Show, Ord, Eq) Palavra chave para derivar classes 80 O Haskell dispõe diversas classes que podem ser derivadas para os novos tipos. ●Show, permite vizualizar os dados na tela ●Ord, permite fazer comparaçoes, < e > ●Eq, permite verificar se dois tipos são iguais
  81. 81. Tipos algébricos – Registro struct Point { x,y: double; }; data Point = Pt Double Double deriving (Show) C Haskell 81
  82. 82. Tipos algébricos – Registro data Point = Pt Double Double deriving (Show) getX :: Point → Double getx Pt x y = x getY :: Point → Double getY Pt x y = x 82 Usando casamento de padrão para pegar um dado valor
  83. 83. Enumerandos enum Dias {Segunda, Terça, Quarta, Quinta, Sexta} data Dias = Segunda | Terça | Quarta | Quinta | Sexta deriving (Show) C Haskell 83
  84. 84. Tipo Booleano data Booleano = Falso | Verdadeiro deriving (Show, Eq) e :: Booleano -> Booleano -> Booleano e Falso _ = Falso e Verdadeiro b = b maior :: Int -> Int -> Booleano maior a b | a > b = Verdadeiro | otherwise = Falso -- a é maior que b e c maior3 a b c = (maior a b) `e` (maior a c) -- maior3 7 5 6 84
  85. 85. União Disjunta em Haskell data Number = Exact Int | Inexact Float Valores: Number = Exact Integer + Inexact Float … Exact(–2) Exact(–1) Exact 0 Exact 1 Exact 2 … … Inexact(–1.0) … Inexact 0.0 … Inexact 1.0 … Cada valor consiste de uma tag, junto ou com um valore inteiro (se a tag is Exact) ou um valor Float (se a tag é Inexact). 85
  86. 86. Exemplo de união disjunta data Number = Exact Int | Inexact Float deriving (Show) pi2 = Inexact 3.1416 rounded :: Number -> Int rounded (Exact i) = i rounded (Inexact r) = round r 86
  87. 87. União Disjunta – Tratando erro data Maybe a = Nothing | Just a 87 Em Haskell existe um tipo de dado muito util em casos onde uma função pode não ter retorno. ●ex. buscar um elemento em uma lista type Aluno = (Int, String) busca :: Int -> [Aluno] -> Maybe String busca mat [] = Nothing busca mat ((x,y):xys) | mat == x = Just y | otherwise = busca mat xys
  88. 88. União Disjunta union { int exact; int inexact; }; data Number = Exact Int | Inexact Float HaskellC 88
  89. 89. Tipos Recursivos data Nat = Zero | Succ Nat data Lista = Nil | Cons Int Lista data ArvoreBin = Vazia | Nodo Int ArvoreBin ArvoreBin 89
  90. 90. Tipos Recursivos Números naturais data Nat = Zero | Succ Nat Nat é um novo tipo com dois construtores Zero :: Nat e Succ :: Nat -> Nat 90
  91. 91. Tipos recursivos data Nat = Zero | Succ Nat deriving (Show) soma :: Nat -> Nat -> Nat soma Zero n = n soma (Succ m) n = Succ (soma m n) mult :: Nat -> Nat -> Nat mult Zero m = Zero mult (Succ m) n = soma n (mult n m) 91
  92. 92. Tipos Recursivos - Lista data List = Nil | Cons Int List deriving (Show) first (Cons a s) = a first Nil = error "vazio" rest (Cons a s) = s rest Nil = error "vazio" 92
  93. 93. Polimorfismo Paramétrico C++ template <typedef T> T maior (T a, T b) { return ( (a>b)? a : b ); } public class Pair<T, S>{ public Pair(T f, S s){ first = f; second = s; } } 93 Java
  94. 94. Polimorfismo paramétrico 94 ● Funções paramétricas ● Tipos de dados paramétrico
  95. 95. ● Uma característica importante de Haskell é o uso de tipos paramétricos ● Muitas funções podem ser definidas em termos de tipos genéricos ● Convenção: usamos a, b, c para tipos genéricos ● Tipos paramétricos comuns, listas e tuplas length :: [a] → Int Tipos Paramétricos em Haskell Pode ser lista de inteiros, de listas .. 95
  96. 96. data List a = Nil | Cons a List deriving (Show) first :: List a → a first (Cons a s) = a first Nil = error "vazio" rest :: List a → List a rest (Cons a s) = s rest Nil = error "vazio" data List Int = Nil | Cons Int List deriving (Show) first :: List → Int first (Cons a s) = a first Nil = error "vazio" rest :: List → List rest (Cons a s) = s rest Nil = error "vazio" Lista de inteiros Lista paramétrica 96 Tipos Paramétricos em Haskell
  97. 97. data ArvBin a = Vazia | Nodo a (ArvBin a) (ArvBin a) deriving Show elem :: ArvBin a -> a elem Vazia = error "arvore vazia" elem (Nodo e _ _) = e esq :: ArvBin a -> ArvBin a esq Vazia = error "arvore vazia" esq (Nodo _ e _) = e dir :: ArvBin a -> ArvBin a dir Vazia = error "arvore vazia" dir (Nodo _ _ d) = d 97 Tipos Paramétricos em Haskell
  98. 98. Definindo as funções de acesso diretamente na definição data ArvBin a = Vazia | Nodo { elem :: a, esq :: (ArvBin a), dir :: (ArvBin a) } deriving Show 98
  99. 99. Restrição no polimorfismo somatodos :: [a] -> a somatodos (x:xs) = x + somatodos xs 99 Esta função pode ser aplicada a qualquer tipo ?
  100. 100. Restrição no polimorfismo somatodos :: (Num a) => [a] -> a somatodos (x:xs) = x + somatodos xs 100 Usando “type classes A função somatodos funciona sobre qualquer “a”, desde que ele seja um Num.
  101. 101. Type class em Haskell class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool 101 ●Uma classe é uma coleção de tipos que suportam certas operações (métodos) comuns ●Uma classe define uma assinatura, similar a uma interface
  102. 102. Classes Básicas em Haskell Eq - tipos com igualdade Ord – tipos ordenados Show – tipos que podem ser transformados em strings Read – tipos legíveis, que pode ser convertido Num – tipos numéricos 102
  103. 103. Instanciando type class data Point = Point Int Int deriving (Show, Eq, Ord, Read) instance Num Point where (+) (Point x1 y1) (Point x2 y2) = Point (x1 + x2) (y1 + y2) 103
  104. 104. data Point = Point Int Int instance Show Point where show (Point x y) = show (x,y) Prelude> Point 4 5 > (4,5) 104 Instanciando type class ● Podemos instanciar qualquer uma das classes pré definidas, mesmo as que são deriváveis, como Read, Show ...
  105. 105. Programas e operações de entrada e saída 105
  106. 106. Operações de entrada e saída 106 Até então, vimos como usar o Haskell via ghci, mas como gerar um programa compilável? Como o Haskell consegue lidar com operações de entrada e saída ? Esse tipo de operação tem efeitos colaterais.
  107. 107. O problema ... Um programa em Haskell consiste num conjunto de funções, sem efeitos colaterais O objetivo de executar qqer programa é ter algum efeito colateral Tensão 107
  108. 108. A solução IO a O tipo das ações de IO que retornam um valor do tipo a 108 Escrever programas interativos em Haskell usando tipos que fazem distinção entre expressões funcionais “puras” de ações “impuras” que podem envolver efeitos colaterais
  109. 109. I/O em Haskell IO Char IO () O tipo das ações de IO que retornam um caracter O tipo das ações que não tem valor de retorno 109
  110. 110. IO em Haskell: O tipo (IO a) Um valor do tipo (IO t) é uma ação que, quando realizada, pode fazer alguma forma de IO antes de devolver um resultado do tipo t. type IO a = World -> (a, World) IO a World outWorld in result::a 110
  111. 111. Meu Primeiro Programa Ou, compile em código nátivo. module Main where main = putStrLn "Hello World!" runghc hello.hs Hello World! ghc hello.hs -o prg1 ./prg1 Hello World! 111 Para rodar interpretado use o runghc:
  112. 112. Funções da biblioteca 112 Funções para escrever na tela putStr :: String -> IO () putStrLn :: String -> IO () Para ler uma linha de caracteres do teclado, podemos usar a função: getLine :: IO(String)
  113. 113. Combinando ações Cada ação é nessa forma: 113 Para combinar ações podemos usar a notação “do”;
  114. 114. Meu segundo programa module Main where main = do input <- getLine putStrLn input 114 Lê uma entrada do usuário e imprime na tela
  115. 115. Meu terceiro programa module Main where ask :: String -> IO String ask question = do putStrLn question getLine main :: IO () main = do nome <- ask "Qual eh o seu nome? " matr <- ask "Qual eh a sua matricula?" putStrLn ("Benvindo "++ nome ++ "!") putStrLn ("Sua matricula eh "++matr) 115
  116. 116. Trabalhando com arquivos import IO import Data.Char main = do str <- readFile "input.txt" writeFile "output.txt" (map toUpper str) 116 Converte todo um arquivo texto para letras maiúsculas. A função readfile retorna uma string contendo todo o arquivo e writeFile escreve uma string em um arquivo.
  117. 117. Funções para string 117 Função lines, quebra uma string pelo marcador de fim de linha lines “linha1nlinha2” = [“linha1”,linha 2] Função words, quebra uma string por separador de palavras,”espaço”. words “uma frase” = [“uma”, frase]
  118. 118. Trabalhando com arquivos main = do str <- readFile "input.txt" print (length (words str)) print (length (lines str)) 118
  119. 119. FIM

×