Programação
Funcional
Tuplas e Definição de Funções
Locais em Haskell
4a. Seção de Slides
Novidades da disciplina:
• Site da disciplina:
http://geocities.yahoo.com.br/lpg3udesc/
• Email: [email protected]
• Márcio Ferreira da Silva
2
Hoje:
Sejam as construções abaixo:
sxy x y z = x + y + z
sXYZ ( x , y, z ) = x + y + z
Qual a diferença entre elas ?
Main> sxyz 3 4 0
7
Main> sXYZ ( 3 , 4, 0 )
7
3
Dicas
import Observe
sumi :: Int -> Int
sumi n
| n <= 0
=0
| otherwise = n + (observe "sumi" (n-1))
4
Tuplas
• A linguagem Haskell permite a definição de tipos
compostos, chamados de tuplas.
• Tuplas são construídas a partir de tipos mais
simples.
• O tipo (t1,t2,...tn)
consiste de tuplas com valores (v1,v2,...vn)
onde v1::t1, v2::t2, vn::tn.
• Enfim, fazer a composição de tipos de dados ...
5
Tuplas
• Definições de novos tipos podem ser introduzidas
pelo comando type.
• Exemplo: informações sobre uma pessoa,
representadas pelo nome, telefone e idade.
1 .type Pessoa = (String, String, Int)
2 .maria :: Pessoa
3 .maria = ("Maria", "32162724", 56)
6
Tuplas
• Tuplas são usadas quando é necessário agrupar
dados, com algum sentido entre eles.
• Exemplo: Uma pessoa tem uma idade, um sexo, um
nome, etc
• Outra utilidade: uma função que pode retornar mais
de um valor como resposta, pois está tudo
encapsulado!
7
Exemplo:
Exemplo: Uma função que retorne o mínimo (menor
valor) e também o máximo de 3 valores inteiros
fornecidos:
menor3maior :: Int -> Int -> Int-> (Int,Int)
menor3maior x y z =
( menor (menor x y) z , maior (maior x y) z)
Aula04> menor3maior
(-6,5)
(-4)
5
(-6)
8
Funções Auxiliares
maior :: Int -> Int -> Int
maior x y =
if x >= y then x else y
menor :: Int -> Int -> Int
menor x y =
if x <= y then x else y
9
Tuplas
• Padrões podem ser utilizados na definição de
funções sobre tuplas.
• Em vez de usar uma variável x para um argumento
de tipo (Int, Int), por exemplo, pode-se usar um
padrão como (x,y).
1 .addPair :: (Int,Int) -> Int
2 .addPair (x,y) = x + y
10
Tuplas
1 .addPair :: (Int,Int) -> Int
2 .addPair (x,y) = x + y
addPair (34, 32)
=
34 casa com x
e 32 casa com y.
11
Tuplas
1 .addPair :: (Int,Int) -> Int
2 .addPair (x,y) = x + y
addPair (34, 32)
= 34 + 32
= 66
12
Tuplas
• Importante: as duas definições seguintes são
diferentes!
1
2
3
4
5
.addPair :: (Int,Int) -> Int
.addPair (x,y) = x + y
.
.addTwo :: Int -> Int -> Int
.addTwo a b = a + b
Main> addPair (34,32)
66
Main> addTwo 34 32
66
Visto no início da aula
13
Tuplas
• Padrões podem conter padrões aninhados.
• Isto é muito útil...
1 .shift :: ((Int,Int),Int) -> (Int,(Int,Int))
2 .shift ((a,b),c) = (a,(b,c))
Main> shift ((1,2),3)
(1,(2,3))
14
Tuplas
• As funções que extraem partes de uma tupla podem
ser especificadas usando casamento de padrões.
1
2
3
4
5
.type Pessoa = (String, String, Int)
.
.nome :: Pessoa -> String
.fone :: Pessoa -> String
.idade :: Pessoa -> Int
15
Tuplas
• Funções que extraem partes de uma tupla podem ser
especificadas usando casamento de padrões.
1
2
3
4
5
6
7
8
9
.type Pessoa = (String, String, Int)
.
.nome :: Pessoa -> String
.fone :: Pessoa -> String
.idade :: Pessoa -> Int
.
.nome (n,f,i) = n
.fone (n,f,i) = f
.idade (n,f,i) = i
16
1 .type Pessoa = (String, String, Int)
2 .
Observe que maria
3 .nome :: Pessoa -> String
4 .fone :: Pessoa -> String
uma função
5 .idade :: Pessoa -> Int
6 .nome (n,f,i) = n
7 .fone (n,f,i) = f
8 .idade (n,f,i) = i
9 .
10 .
maria :: Pessoa
11 .
maria = ("Maria Antonia", "32162724", 56)
Main> nome maria
"Maria Antonia"
Main> idade maria
56
é
E nome também é uma
função, cujo argumento é
uma função definida por
uma tupla
17
Tuplas
• Haskell possui duas funções de extração prédefinidas para tuplas de 2 elementos (pares).
1 .fst (x,y) = x
2 .snd (x,y) = y
Main> fst (1,2)
1
Main> snd (1,2)
2
18
Definições de Funções
• Por enquanto, as definições de funções estudadas
são da forma:
fun p1 p2 ... pn
| g1
| g2
...
| otherwise
= e1
= e2
= er
19
Definições Locais
• Cada equação pode também ser seguida por uma
lista de definições locais.
• Essas definições são escritas após a palavra-chave
where.
1
2
3
4
5
6
.sumSquares :: Int -> Int -> Int
.sumSquares m n
. = sqM + sqN
.
where
.
sqM = m * m
.
sqN = n * n
20
Definições Locais
• Formato geral:
fun p1 p2 ... pn
| g1
= e1
...
| otherwise
= er
where
v1 = r1
v2 a1...ak = r2
...
Indentação é
importante. Define o
conceito de “Bloco”
Definições locais podem
incluir funções!
21
1
2
3
4
5
6
.sumSquares :: Int -> Int -> Int
.sumSquares m n
. = sqM + sqN
.
where
.
sqM = m * m
.
sqN = n * n
• Exemplo com definição de função local:
1
2
3
4
5
.sumSquares
.sumSquares
. = sq m +
.
where
.
sq x =
:: Int -> Int -> Int
m n
sq n
x * x
sq é local...
Visível
apenas em
sumSquares
22
Definições Locais
• É possível fazer também definições locais a
expressões, usando a palavra-chave let.
Main> let x = 5 in x^2 + 2*x - 4
31
• Se forem usadas 2 ou mais definições, devem ser
separadas por ";" .
Main> let x = 5; y = 4 in x^2 + 2*x - y
31
23
Regras de Escopo
• O escopo de uma definição é a parte do programa
onde ela é visível.
• As definições no primeiro nível de indentação de um
script haskell são visíveis em todo o programa.
• A ordem de definição não importa.
1
2
3
4
5
6
.isOdd, isEven :: Int -> Bool
.
.isOdd 0 = False
.isOdd n = isEven (n-1)
.isEven 0 = True
.isEven n = isOdd (n-1)
24
Regras de Escopo
• Definições locais (cláusulas where) têm escopo mais
reduzido, assim como as variáveis na definição de
uma função.
Definições locais podem
1 .maxsq x y
ser usadas antes de serem
2 . | sqx > sqy
= sqx
definidas.
3 . | otherwise
= sqy
4
5
6
7
8
.
.
.
.
.
where
sqx = sq x
sqy = sq y
sq :: Int -> Int
sq z = z * z
Declaração do tipo
pode ser feita
localmente.
25
Regras de Escopo
• Definições locais (cláusulas
wherede
) têm
mais
Escopo
x, yescopo
,
reduzido, assim como as variáveis
nasqdefinição
de
sqx, sqy e
.
uma função.
1
2
3
4
5
6
7
8
.maxsq x y
. | sqx > sqy
= sqx
. | otherwise
= sqy
.
where
.
sqx = sq x
.
sqy = sq y
.
sq :: Int -> Int
.
sq z = z * z
Escopo de z.
26
Regras de Escopo
• Se um mesmo nome é utilizado mais de uma vez,
vale a definição mais local.
1
2
3
4
5
6
7
8
.maxsq x y
. | sqx > sqy
= sqx
. | otherwise
= sqy
.
where
.
sqx = sq x
.
sqy = sq y
.
sq :: Int -> Int
.
sq x = x * x
Nome "x" é redefinido
localmente.
27
Exemplos
• Problema: construir uma função
max3oc :: Int -> Int -> Int -> (Int,Int)
que retorna o máximo (maior) de 3 inteiros, e também
o número de vezes que esse maior valor ocorre entre
os 3.
• Exemplo de execução:
Main> max3oc 10 30 20
(30,1)
Main> max3oc 15 12 15
(15,2)
28
Exemplos
• Solução natural: achar o máximo/maior e contar
quantas vezes ocorre entre os 3 valores.
1
2
3
4
5
6
7
.max3oc :: Int -> Int -> Int -> (Int,Int)
.
.max3oc x y z
. = (max, igCont)
.
where
.
max
= maxi3 x y z
.
igCont
= iguais3 max x y z
29
Exemplos
• Para achar o máximo entre 3 valores, pode-se usar a
função que encontra o máximo entre 2 valores.
1
2
3
4
5
6
7
.maxi :: Int -> Int -> Int
.maxi x y
. | x >= y
= x
. | otherwise
= y
.
.maxi3 :: Int -> Int -> Int -> Int
.maxi3 x y z = maxi x (maxi y z)
30
Exemplos
• Voltando ao problema inicial...
1
2
3
4
5
.max3oc x y z
. = (max, igCont)
.
where
.
max
= maxi3 x y z
.
igCont
= iguais3 max x y z
• Como definir
iguais3 :: Int -> Int -> Int -> Int -> Int
???
31
Exemplos
• Uma solução:
1
2
3
4
5
6
.iguais3 v a
. = va + vb
.
where
.
va = if
.
vb = if
.
vc = if
b c
+ vc
a==v then 1 else 0
b==v then 1 else 0
c==v then 1 else 0
• OBS: if c then e1 else e2 retorna e1 se c for
True, e retorna e2, se c for False.
32
Exemplos
• A definição pode ser melhorada, eliminando a
repetição de 3 comparações análogas:
1
2
3
4
5
6
.iguais3 v a
. = va + vb
.
where
.
va = if
.
vb = if
.
vc = if
b c
+ vc
a==v then 1 else 0
b==v then 1 else 0
c==v then 1 else 0
33
Exemplos
• A definição pode ser melhorada, eliminando a
repetição de 3 comparações análogas:
1
2
3
4
5
.iguais3 v a b c
. = igv a + igv b + igv c
.
where
.
igv :: Int -> Int
.
igv x = if x==v then 1 else 0
O valor ”v" é maior já
encontrado
34
Mais Exemplos ..
Um sistema de menu’s....
main =
imp_menu
imp_menu =
do
putStrLn
putStrLn
putStrLn
putStrLn
putStrLn
putStr
le_opcao
Criando um
executável...
Tudo começa
em main
"\n ********************"
" Opção i: Incluir
"
" Opção e: Excluir
"
" Opção s: Sair
"
" ********************"
" Digite i, e ou s: "
35
Continuando ..
le_opcao =
do opcao <- getChar
f_menu opcao
f_menu i =
do
case (i)
'i' ->
'e' ->
's' ->
_
->
of
putStrLn "\n Chamou a funcao 1 !!!"
putStrLn "\n Chamou a funcao 2 !!!"
putStrLn "\n Chamou a funcao 3 !!!"
imp_menu
36
Finalizando ...
• Temos palavras reservadas como: do, case, let,
where, in, if, then, else, of, etc, a serem
utilizadas nas funções;
• Diríamos que é a parte sequencial das linguagens
funcionais, que ainda nos prende as Máquinas de
Von Neumann (sequenciais);
• Contudo, o uso delas pode ser contornado (se
quiser, opcional), usando um estilo 100% funcional
de se programar;
• Estas seguem regras de escopo;
• Estas seguem uma identação de blocos. Cuidar...
37
Download

Visualizar - GEOCITIES.ws