paradigma funcional - caso de estudo haskell

135
Prof. Sérgio Souza Costa Paradigma Funcional Caso de Estudo: Haskell “Life is too short for imperative programming”

Upload: sergio-souza-costa

Post on 18-Dec-2014

2.339 views

Category:

Technology


2 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Paradigma Funcional - Caso de Estudo Haskell

Prof. Sérgio Souza Costa

Paradigma FuncionalCaso de Estudo: Haskell

“Life is too short for imperative programming”

Page 2: Paradigma Funcional - Caso de Estudo Haskell

Sobre mim

Sérgio Souza CostaProfessor - UFMADoutor em Computação Aplicada (INPE)

[email protected]

https://sites.google.com/site/profsergiocosta/home

https://twitter.com/profsergiocosta

http://gplus.to/sergiosouzacosta

http://www.slideshare.net/skosta/presentations?order=popular

Page 3: Paradigma Funcional - Caso de Estudo Haskell

John McCarthy (Boston, 4 de setembro de 1927 — 23 de outubro de 2011[1]) Criador da linguagem Lisp, segunda linguagem de programação.

Page 4: Paradigma Funcional - Caso de Estudo Haskell

Life is too short for imperative programming”

John Hughes

Page 5: Paradigma Funcional - Caso de Estudo Haskell

Programação funcional

● Um paradigma sem● Váriaveis

● Loops

● Ponteiros

● ...

Page 6: Paradigma Funcional - Caso de Estudo Haskell

Mudança de paradigma

Page 7: Paradigma Funcional - Caso de Estudo Haskell

PARADIGMAS DE PROGRAMAÇÃO

• Modelo, padrão ou estilo de programação suportado por linguagens que agrupam certas características comuns

Como programar ?

IMPERATIVO DECLARATIVO

PROCEDURALORIENTADO A

OBJETOSFUNCIONAL LÓGICO

Page 8: Paradigma Funcional - Caso de Estudo Haskell

É dificil programar em linguagem funcional ?

Page 9: Paradigma Funcional - Caso de Estudo Haskell

Basta abrir a cabeça

Page 10: Paradigma Funcional - Caso de Estudo Haskell

Orientação a objetos 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 )

Page 11: Paradigma Funcional - Caso de Estudo Haskell

Programação funcional é um estilo de programaçãoque permite:

- Reuso de código (composição de função)- Eliminação de bug (via imutabilidade (não existe mudança de valores de váriáveis))

Orientação a objetos Vs Funcional

Page 12: Paradigma Funcional - Caso de Estudo Haskell

Programaçao funcional

● Não existem variáveis○ Expressões

● Não existem comandos○ Funções

● Não existem efeitos colaterais○ Declarações

● Não há armazenamento○ Funções de alta ordem○ Lazy evaluation○ Recursão

● Fluxo de controle: expressões condicionais + recursão

Page 13: Paradigma Funcional - Caso de Estudo Haskell

Vantagens● Códigos suscintos e concisos

○ Menor tempo de desenvolvimento○ Manutenabilidade

● Códigos seguros● Reusabilidade● Facilidade de escrita, suporte a abstrações● Confiabilidade, segurança

Page 14: Paradigma Funcional - Caso de Estudo Haskell

Vantagens – Suscintos e Concisos

qs [] = []qs (x:xs) = qs [y | y <- xs, y < x] ++ [x] ++ qs [y | y <- xs, y >= x]

Quick sort – Haskell

Page 15: Paradigma Funcional - Caso de Estudo Haskell

Quick sort em 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;}

Page 16: Paradigma Funcional - Caso de Estudo Haskell

Quick sort em 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); }

Page 17: Paradigma Funcional - Caso de Estudo Haskell

Desvantagens

O computador não é funcional

● Maior custo de processamento● Maior consumo de memória

Page 18: Paradigma Funcional - Caso de Estudo Haskell

Trade-offTempo de desenvolvimento

Versus

tempo de execução

Page 19: Paradigma Funcional - Caso de Estudo Haskell

Conceitos chaves

● Expressões● Funções● Polimorfismo paramétrico ●

● E em algumas linguagens:●

● Abstração de dados● Avaliação preguiçosa.

Page 20: Paradigma Funcional - Caso de Estudo Haskell

Conceitos chaves

● Expressão é um conceito chave, pois seu proposito é 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(abstrai) 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 ..

Page 21: Paradigma Funcional - Caso de Estudo Haskell

Conceitos chavesAbstração de dados é o conceito chave nas linguagens funcionais modernas, tais como ML e HASKELL. Todas as operações de tipos abstratos são constantes e funções.

Polimorfismo paramétrico é um conceito chave, pois ele permite que uma função opere sobre valores de uma familia de tipos, ao invés de apenas um tipo. Na pratica, muitas funções são naturalmente polimorficas, e o polimorfismo parametrico incrementar o poder e a expressividade das linguagens funcionais

Avaliação preguiçosa e baseada na noção que uma expressão só será avaliada se for usada.

Page 22: Paradigma Funcional - Caso de Estudo Haskell

Caso de Estudo: Haskell

●Haskell: Uma abordagem prática: ●

●Real World Haskell●http://book.realworldhaskell.org/read/●

Page 23: Paradigma Funcional - Caso de Estudo Haskell

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

Page 24: Paradigma Funcional - Caso de Estudo Haskell

Haskell na Industria

http://www.haskell.org/haskellwiki/Haskell_in_industry

Page 25: Paradigma Funcional - Caso de Estudo Haskell

Elementos básicos

● Expressões e funções● Tipos e valores● Tuplas● Listas

Page 26: Paradigma Funcional - Caso de Estudo Haskell

Expressões

● Em Haskell, construimos expressões a partir de:

● constantes

● operadores

● aplicação de funções

● (parênteses)

Page 27: Paradigma Funcional - Caso de Estudo Haskell

Expressões

● Constantes:

-3.459True'a'"hello"[1,2,4,9]

● Aplicação de funções:

even 47twice (-2)

Page 28: Paradigma Funcional - Caso de Estudo Haskell

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

Page 29: Paradigma Funcional - Caso de Estudo Haskell

Avaliação preguiçosa

• Estratégia call-by-value --- Avalia primeiro o argumento antes de aplicar a função (Pascal, C, Java, etc).

(\x -> x+1) (2+3)= (x+1)+ 5= 5+1= 6

(\x -> x+1) (2+3)= (2+3)+1= 5+1= 6

• 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)

Page 30: Paradigma Funcional - Caso de Estudo Haskell

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)

Page 31: Paradigma Funcional - Caso de Estudo Haskell

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).

Page 32: Paradigma Funcional - Caso de Estudo Haskell

Tipos em Haskell - Primitivos

●Bool Boleanos ●Char Caracteres ●Int Inteiros de 32-bits●Integer Inteiros de tam ilimitado●Float Ponto flutuante ●Double Dupla precisão

Page 33: Paradigma Funcional - Caso de Estudo Haskell

Toda expressão tem um tipo

Os tipos podem ser enferidos

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]

Page 34: Paradigma Funcional - Caso de Estudo Haskell

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.

Page 35: Paradigma Funcional - Caso de Estudo Haskell

Função

Page 36: Paradigma Funcional - Caso de Estudo Haskell

Definição de 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

Page 37: Paradigma Funcional - Caso de Estudo Haskell

Definição de funções

● A definicao de uma funçao 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 parametros de entrada da função.

● f1 :: Int → Int → Intf1 x y = x*y

Page 38: Paradigma Funcional - Caso de Estudo Haskell

Funções e constantes

● Funções generalizam as expressões através de variáveis.

-- PI

pi = 3.14159

-- area e circunferencia de circulo

circumf r = 2 * pi * r

area rad = pi * rad^2

Page 39: Paradigma Funcional - Caso de Estudo Haskell

Aplicação de funções em Haskell e na matemática

Matemáticaf (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

Page 40: Paradigma Funcional - Caso de Estudo Haskell

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]

Page 41: Paradigma Funcional - Caso de Estudo Haskell

Expressão de seleção

Considere uma função que dado dois valores, ela retorna o menor:

A estratégia para resolução do problema é com uso de uma expressão de seleção

menor x y =

se x <= y então o resultado da expressão é x

senão o resultado é y

Page 42: Paradigma Funcional - Caso de Estudo Haskell

Expressão de seleção

if <condição> then <resultado 1>

else <resultado2>

menor :: Int -> Int -> Intmenor x y = if x <= y then x

else y

Page 43: Paradigma Funcional - Caso de Estudo Haskell

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 mais elegante aos “ifs”

-- fatorial

fat :: Integer -> Integerfat 0 = 1fat n = fat (n-1) * n

Page 44: Paradigma Funcional - Caso de Estudo Haskell

Listas

● Uma lista é uma sequencia 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)

Page 45: Paradigma Funcional - Caso de Estudo Haskell

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"

Page 46: Paradigma Funcional - Caso de Estudo Haskell

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"

Page 47: Paradigma Funcional - Caso de Estudo Haskell

Listas

Pode se definir uma lista indicando os limites inferior e superior:[<limite-inferior> .. <limite-superior>]

Page 48: Paradigma Funcional - Caso de Estudo Haskell

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]

Page 49: Paradigma Funcional - Caso de Estudo Haskell

Listas por compreensãoA 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 preposiçõ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

Page 50: Paradigma Funcional - Caso de Estudo Haskell

● Um construtor de processamento de listas em linguagem de programação, a notação matemática é a sequinte:

● Outros exemplos● Por exemplo, as 10 primeiras potências de 2:[2 ^ x | x <- [1..10] ]● Todos os numeros pares maiores que 1 e menores

que 100:[ x | x <- [1..100] , par x ]

Listas por compreensão

S = [ x | x<-[0..], x^2>3 ]

Page 51: Paradigma Funcional - Caso de Estudo Haskell

Listas por compreensão

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,84,86,88,90,92,94,96,98]

Page 52: Paradigma Funcional - Caso de Estudo Haskell

Listas por compreensão

Listas com mais um gerador

Page 53: Paradigma Funcional - Caso de Estudo Haskell

Comportamento situacional em funções sobre Listas

isempty :: [a] -> Boolisempty [] = Trueisempty anythingElse = False

length [] = 0length (x : xs) = 1 + length xs

head [] = error "head []"head (x:xs) = x

Page 54: Paradigma Funcional - Caso de Estudo Haskell

Recursão

Um conceito básico em Haskell é o uso de recursão para definição de funções

length :: [a] -> Intlength [] = 0length (x : xs) = 1 + length xs

Page 55: Paradigma Funcional - Caso de Estudo Haskell

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:● Decremente um valor para cada chamada● Tome um valor de uma lista a cada chamada

Page 56: Paradigma Funcional - Caso de Estudo Haskell

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

Page 57: Paradigma Funcional - Caso de Estudo Haskell

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:

Page 58: Paradigma Funcional - Caso de Estudo Haskell

Avaliação de Funções Recursivas

length [] = 0length (x : xs) = 1 + length xs

length (1 : 2 : 4 : [])

Page 59: Paradigma Funcional - Caso de Estudo Haskell

Avaliação de Funções Recursivas

length [] = 0length (x : xs) = 1 + length xs

length (1 : 2 : 4 : []) 1 + length (2 : 4 : [])

Page 60: Paradigma Funcional - Caso de Estudo Haskell

Avaliação de Funções Recursivas

length [] = 0length (x : xs) = 1 + length xs

length (1 : 2 : 4 : []) 1 + 1 + length (4 : [])

Page 61: Paradigma Funcional - Caso de Estudo Haskell

Avaliação de Funções Recursivas

length [] = 0length (x : xs) = 1 + length xs

length (1 : 2 : 4 : []) 1 + length (2 : 4 : []) 1 + 1 + length (4 : []) 1 + 1 + 1 + length []

Page 62: Paradigma Funcional - Caso de Estudo Haskell

Avaliação de Funções Recursivas

length [] = 0length (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

Page 63: Paradigma Funcional - Caso de Estudo Haskell

Recursos avançados

1. Definições locais,2. Importando bibliotecas externas,3. Funções de segunda ordem4. Trabalhando com entrada e saída

Page 64: Paradigma Funcional - Caso de Estudo Haskell

Definições locais

Para melhor a legibilidade de um código, podemos usar a clausula “where” para fazer definiçoes visíveis somente por uma dada função.

raizes (a, b, c) = (x1,x2) where delta = sqrt ( b^2 - 4*a*c) x1 = ((-b) + delta) / (2*a) x2 = ((-b) - delta) / (2*a)

Page 65: Paradigma Funcional - Caso de Estudo Haskell

Type sinonimos

● Em Haskell, é possível criar sinonimos de tipos, ex:

type Point = (Int, Int)type Polygon = [Point]

p1 :: PointP1 = (1,4)

pol1:: Polygonpol1 = [(1,1),(1,2),(3,1),(1,1)]

Page 66: Paradigma Funcional - Caso de Estudo Haskell

Avaliação parcial

Haskell distingue entre operadores and funções:Operadores tem 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

Page 67: Paradigma Funcional - Caso de Estudo Haskell

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

Page 68: Paradigma Funcional - Caso de Estudo Haskell

Avaliação parcial

A função divideByTen 200 é equivalente a 200 / 10, ou (/10) 200

divideByTen :: (Floating a) => a -> a divideByTen = (/10)

Page 69: Paradigma Funcional - Caso de Estudo Haskell

Funções são valores de primeira classe

● 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

Page 70: Paradigma Funcional - Caso de Estudo Haskell

Funções como argumentos

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.

twice :: (a -> a) -> a -> a twice f x = f (f x)

Page 71: Paradigma Funcional - Caso de Estudo Haskell

Map

A função map aplica uma função a todos os elementos de uma lista.

map :: (a -> b) -> [a] -> [b]

Main> map double [1,3,5,7][2,6,10,14]

Page 72: Paradigma Funcional - Caso de Estudo Haskell

Map

Map pode ser definido por recursão ou por compreensão de listas

●Ou por compreensão de lista

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

Page 73: Paradigma Funcional - Caso de Estudo Haskell

Map – Mais exemplos

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]

Page 74: Paradigma Funcional - Caso de Estudo Haskell

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 (: [])

Page 75: Paradigma Funcional - Caso de Estudo Haskell

Filter

●A função filter seleciona os elementos de uma lista que satisfazem a um predicado

filter :: (a -> Bool) -> [a] -> [a]

Main> filter even [1..10][2,4,6,8,10]

Page 76: Paradigma Funcional - Caso de Estudo Haskell

Filter

●Pode ser definido como compreensão de listas ou por recursão

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

11/4/11

Page 77: Paradigma Funcional - Caso de Estudo Haskell

Comprimindo para um único valor

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

f [] = vf (x:xs) = x � f xs

Page 78: Paradigma Funcional - Caso de Estudo Haskell

Comprimindo para um único valor

sum [] = 0sum (x:xs) = x + sum xs

product [] = 1product (x:xs) = x * product xs

and [] = Trueand (x:xs) = x && and xs

11/4/11

Page 79: Paradigma Funcional - Caso de Estudo Haskell

Comprimindo para um unico valor

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

sum = foldr (+) 0

product = foldr (*) 1

and = foldr (&&) True

Page 80: Paradigma Funcional - Caso de Estudo Haskell

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)

Page 81: Paradigma Funcional - Caso de Estudo Haskell

Composição de Funções

(f . g) x = f (g x)

> ( (*2) . (*5) ) 8> 80

Page 82: Paradigma Funcional - Caso de Estudo Haskell

Abstração de dados

Tipos enumerados (enumerated no C),Tipos cartesianos (struct no C),Uniões disjunta (union no C)Tipos recursivos

Page 83: Paradigma Funcional - Caso de Estudo Haskell

O que vimos até então...

Usamos os tipos existentes em Haskell ● Primitivos: Int, String, Bool● Compostos: Listas e tuplas

Aprendemos criar sinonimos :

type Matricula = Inttype Nome = Stringtype Salario = Doubletype Funcionario = (Matricula, Nome, Salario)

Page 84: Paradigma Funcional - Caso de Estudo Haskell

Qual o problema com os sínonimos?

11/4/11

Page 85: Paradigma Funcional - Caso de Estudo Haskell

Considerem os seguintes códigostype Matricula = Inttype Nome = Stringtype Salario = Doubletype Funcionario = (Matricula, Nome, Salario)

funcionarios :: [Funcionario]funcionarios = [(1235,"joao", 580), (256,"jose", 590)]

aumentaSalario :: Funcionario -> FuncionarioaumentaSalario (m,n,s) = (m,n,s+(0.1*s))

type Nota = Doubletype Alunos = (Matricula, Nome, Nota)

alunos :: [Alunos]alunos = [(1,"antonio", 50.6), (6,"maria", 70)]

– eu poderia aplicar aumentaSalario a alunos, pois são a mesma tupla, – apenas com nomes diferentes11/4/11

Page 86: Paradigma Funcional - Caso de Estudo Haskell

Usando tipos algébricos do Haskell

● Nós definimos um novo tipo de dado usando o palavra-chave data.

Data Funcionario = Funcionario Int String Double

type Matricula = Inttype Nome = Stringtype Salario = Double

Data Funcionario = Funcionario Matricula Nome Salario

Page 87: Paradigma Funcional - Caso de Estudo Haskell

Tipos Compostos

Os tipos algebricos 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)

Page 88: Paradigma Funcional - Caso de Estudo Haskell

Tipos algébricos

● Diferenças entre nome de tipos e construtor de tipos:

O nome do tipo e dos construtores não precisa ser iguais.

data InfoLivro = Livro Int String [String]

Nome do tipo

Construtor de tipo

11/4/11

Page 89: Paradigma Funcional - Caso de Estudo Haskell

Tipos algébricos

● 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

data Matricula = Matricula Int deriving (Show, Ord, Eq)

Palavra chave para derivar classes

11/4/11

Page 90: Paradigma Funcional - Caso de Estudo Haskell

Tipos algébricos – Registro

Comparação com C

struct Point {x,y: double;

};

data Point = Pt Double Double deriving (Show)

C

Haskell

Page 91: Paradigma Funcional - Caso de Estudo Haskell

Tipos algébricos – Registro

● Usando casamento de padrão para pegar um dado valor

data Point = Pt Double Double deriving (Show)

getX :: Point → Doublegetx Pt x y = x

getY :: Point → DoublegetY Pt x y = x

11/4/11

Page 92: Paradigma Funcional - Caso de Estudo Haskell

Enumerados

● Comparação com C

enum Dias {Segunda, Terça, Quarta, Quinta, Sexta}

data Dias = Segunda | Terça | Quarta| Quinta | Sexta deriving (Show)

C

Haskell

11/4/11

Page 93: Paradigma Funcional - Caso de Estudo Haskell

Tipo Booleano

● Criando e usando o seu próprio tipo booleano

data Booleano = Falso | Verdadeiro deriving (Show, Eq)

e :: Booleano -> Booleano -> Booleanoe Falso _ = Falsoe Verdadeiro b = b

maior :: Int -> Int -> Booleanomaior a b | a > b = Verdadeiro | otherwise = Falso

-- a é maior que b e cmaior3 a b c = (maior a b) `e` (maior a c)-- maior3 7 5 6

Page 94: Paradigma Funcional - Caso de Estudo Haskell

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).

11/4/11

Page 95: Paradigma Funcional - Caso de Estudo Haskell

Exemplo de união disjunta

data Number = Exact Int | Inexact Float deriving (Show)

pi2 = Inexact 3.1416 rounded :: Number -> Introunded (Exact i) = irounded (Inexact r) = round r

11/4/11

Page 96: Paradigma Funcional - Caso de Estudo Haskell

União Disjunta – Tratando erro

● Em Haskell existe um tipo de dado muito util em casos onde uma função pode nao ter retorno.●ex. buscar um elemento em uma lista

data Maybe a = Nothing | Just a

Page 97: Paradigma Funcional - Caso de Estudo Haskell

União Disjunta – Tratando erro

● Exemplo, buscando em uma lista

type Aluno = (Int, String)busca :: Int -> [Aluno] -> Maybe String

busca mat [] = Nothingbusca mat ((x,y):xys) | mat == x = Just y | otherwise = busca mat xys

Page 98: Paradigma Funcional - Caso de Estudo Haskell

União Disjunta

Comparando com a linguagem C

union {int exact;int inexact;

};

data Number = Exact Int | Inexact Float

Haskell C

Page 99: Paradigma Funcional - Caso de Estudo Haskell

Tipos Recursivos

Exemplos de tipos recursivos:

data Nat = Zero | Succ Nat

data Lista = Nil | Cons Int Lista

data ArvoreBin = Vazia | Nodo Int ArvoreBin ArvoreBin

Page 100: Paradigma Funcional - Caso de Estudo Haskell

Tipos Recursivos

Números naturais

data Nat = Zero | Succ Nat

Nat é um novo tipo com dois construtores

Zero :: Nat e Succ :: Nat -> Nat

Page 101: Paradigma Funcional - Caso de Estudo Haskell

Tipos recursivos

● Implementando as operações básicas.

data Nat = Zero | Succ Nat deriving (Show)

soma :: Nat -> Nat -> Natsoma Zero n = nsoma (Succ m) n = Succ (soma m n)

mult :: Nat -> Nat -> Natmult Zero m = Zeromult (Succ m) n = soma n (mult n m)

Page 102: Paradigma Funcional - Caso de Estudo Haskell

Tipos Recursivos - Lista

● A implementação mínima de uma lista:

data List = Nil | Cons Int Listderiving (Show)

first (Cons a s) = afirst Nil = error "vazio"

rest (Cons a s) = srest Nil = error "vazio"

Page 103: Paradigma Funcional - Caso de Estudo Haskell

Atividade

A partir da lista dada anteriormente, implemente as seguintes funções:

ultimo :: List -> Int

soma :: List -> Int

mapeia :: (Int->Int) -> List -> List – equivalente ao “map”

Page 104: Paradigma Funcional - Caso de Estudo Haskell

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; } }

Java

Page 105: Paradigma Funcional - Caso de Estudo Haskell

Polimorfismo paramétrico

● Funções paramétricas● Tipos de dados paramétrico

Page 106: Paradigma Funcional - Caso de Estudo Haskell

Tipos Paramétricos em Haskell

● 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

Pode ser lista de inteiros, de listas ..

Page 107: Paradigma Funcional - Caso de Estudo Haskell

data List a = Nil | Cons a Listderiving (Show)

first :: List a → afirst (Cons a s) = afirst Nil = error "vazio"

rest :: List a → List arest (Cons a s) = srest Nil = error "vazio"

data List Int = Nil | Cons Int Listderiving (Show)

first :: List → Intfirst (Cons a s) = afirst Nil = error "vazio"

rest :: List → List rest (Cons a s) = srest Nil = error "vazio"

Lista de inteiros Lista paramétrica

Tipos Paramétricos em Haskell

Page 108: Paradigma Funcional - Caso de Estudo Haskell

data ArvBin a = Vazia | Nodo a (ArvBin a) (ArvBin a) deriving Show

elem :: ArvBin a -> aelem Vazia = error "arvore vazia"elem (Nodo e _ _) = e

esq :: ArvBin a -> ArvBin aesq Vazia = error "arvore vazia"esq (Nodo _ e _) = e

dir :: ArvBin a -> ArvBin adir Vazia = error "arvore vazia"dir (Nodo _ _ d) = d

Tipos Paramétricos em Haskell

Page 109: Paradigma Funcional - Caso de Estudo Haskell

Definindo as funções de acesso diretamento na definição

● Equivalente a implementação anterior

data ArvBin a = Vazia | Nodo {

elem :: a, esq :: (ArvBin a),dir :: (ArvBin a)

} deriving Show

Page 110: Paradigma Funcional - Caso de Estudo Haskell

Restrição no polimorfismo

● Considere a seguinte função,● somar todos os valores de uma lista

somatodos :: [a] -> asomatodos (x:xs) = x + somatodos xs

Qual o problema nessa definição ?

Page 111: Paradigma Funcional - Caso de Estudo Haskell

Restrição no polimorfismo

● Considere a seguinte função,● somar todos os valores de uma lista

somatodos :: [a] -> asomatodos (x:xs) = x + somatodos xs

Qual o problema nessa definição ?

Page 112: Paradigma Funcional - Caso de Estudo Haskell

Restrição no polimorfismo

● Usando “type classes”

A função somatodos funciona sobre qualquer “a”, desde que ele seja um Num.

somatodos :: (Num a) => [a] -> asomatodos (x:xs) = x + somatodos xs

Page 113: Paradigma Funcional - Caso de Estudo Haskell

Type class em Haskell

●Uma classe é uma coleção de tipos que suportam certas operações (métodos) comuns●Uma classe define uma assinatura

class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool

Page 114: Paradigma Funcional - Caso de Estudo Haskell

Classes Básicas em Haskell

Eq - tipos com igualdade

Ord – tipos ordenados

Show – tipos mostráveis

Read – tipos legíveis, que pode ser convertido

Num – tipos numéricos

11/4/11

Page 115: Paradigma Funcional - Caso de Estudo Haskell

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)

Page 116: Paradigma Funcional - Caso de Estudo Haskell

● Podemos instanciar qualquer uma das classes pré definidas, mesmo as que são derivaveis, como Read, Show ...

data Point = Point Int Int

instance Show Point whereshow (Point x y) = show (x,y)

Prelude> Point 4 5> (4,5)

Instanciando type class

Page 117: Paradigma Funcional - Caso de Estudo Haskell

Hierarquia - type class

Page 118: Paradigma Funcional - Caso de Estudo Haskell

Programas e operações de entrada e saída

Page 119: Paradigma Funcional - Caso de Estudo Haskell

Operações de entrada e saída

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.

Page 120: Paradigma Funcional - Caso de Estudo Haskell

O problema ...

Um programa em Haskell consiste num conjunto de funções,

semefeitos colaterais

O objetivo de executar qqer programa é ter

algum efeito colateralTensão

Page 121: Paradigma Funcional - Caso de Estudo Haskell

A solução

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

IO a

O tipo das ações de IO que retornam um valor do tipo a

Page 122: Paradigma Funcional - Caso de Estudo Haskell

I/O em Haskell

Exemplos de IOs

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

Page 123: Paradigma Funcional - Caso de Estudo Haskell

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 aWorld out

World in

result::a

Page 124: Paradigma Funcional - Caso de Estudo Haskell

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./prg1Hello World!

Para rodar interpretado use o runghc:

Page 125: Paradigma Funcional - Caso de Estudo Haskell

Funções da biblioteca

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)

Page 126: Paradigma Funcional - Caso de Estudo Haskell

Combinando ações

Para combinar ações podemos usar a notação “do”;

Cada ação é nessa forma:

Page 127: Paradigma Funcional - Caso de Estudo Haskell

Meu segundo programa

Lê uma entrada do usuário e imprime na tela

module Main wheremain = do

input <- getLine putStrLn input

Page 128: Paradigma Funcional - Caso de Estudo Haskell

Incrementando um pouco mais

module Main where

ask :: String -> IO Stringask 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)

Page 129: Paradigma Funcional - Caso de Estudo Haskell

Lendo outros tipos, e uso de funções dentro de um IOask :: String -> IO Doubleask question = do

putStrLn question readLn

main = do a <- ask "valor de a" b <- ask "valor de b" c <- ask "valor de c" let rs = raizes (a,b,c) let r1 = fst rs let r2 = snd rs print ("raiz 1 eh " ++ (show r1) ++ ", raiz 2 eh " ++ (show r2) )

Page 130: Paradigma Funcional - Caso de Estudo Haskell

Trabalhando com arquivos

Converte todo um arquivo texto para letras maiusculas.A função readfile retorna uma string contendo todo o arquivo e writeFile escreve uma string em um arquivo.

import IOimport Data.Char main = do

str <- readFile "input.txt"writeFile "output.txt" (map toUpper str)

Page 131: Paradigma Funcional - Caso de Estudo Haskell

Funções para string

Função lines, quebra uma string pelo marcador de fim de linha

lines “linha1\nlinha2” → [“linha1”,linha 2]

Função words, quebra uma string por separador de plavras,”espaço”. words “uma frase”-> [“uma”, frase]

Page 132: Paradigma Funcional - Caso de Estudo Haskell

Trabalhando com arquivos

● Número de palavras e de linhas de um arquivo:

main = do str <- readFile "input.txt"print (length (words str))Print (length (lines str))

Page 133: Paradigma Funcional - Caso de Estudo Haskell

Trabalhando com arquivos

● Usando a função “iterative”, convertendo todas as letras de um arquivo para maiuscula.

main = interact conv where conv s = (map toUpper s)

prog1 < arquivoentr.txt > arquivosaida.txt

Page 134: Paradigma Funcional - Caso de Estudo Haskell

Trabalhando com argumentosimport System.Environment

main:: IO()main = do

args <- getArgs let arg1 = head argsprint ("o primeiro argumento eh " ++ arg1)

sergio@sergio-laptop:~$ runghc arg.hs teste"o primeiro argumento eh teste"

Page 135: Paradigma Funcional - Caso de Estudo Haskell

FIM