Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

VictorCacciari

[Haskell Aula 02] Pattern Matching

Recommended Posts

Aula 02 -> Pattern Matching

 

Olá Pessoal!

Aula passada estavamos falando em listas, agora vamos aprender a usar as listas (e outras coisas) nas nossas funções.

 

Haskell, assim como algumas outras linguagens funcionais, possui um mecanismo chamado 'pattern matching', do inglês 'concordância de padrões',

e sem esse cara seria um trabalho imenso programar em Haskell.

 

Como funciona?

É a coisa mais fácil do mundo!

Vamos definir a função que calcula o fatorial de um número:

fatorial :: Int -> Int
fatorial n = if n == 1
             then 1
             else n * (fatorial (n-1))

Fantástico, mas esse 'if' só está ocupando espaço, isso sim!

Esse tipo de condição podemos impor diretamente na declaração dos parametros da fução, olhem:

fatorial :: Int -> Int
fatorial 1 = 1
fatorial n = n * (fatorial (n-1))
Agora temos uma função por ramos, e o Haskell escolhe sozinho qual o ramo apropriado a utilizar.

 

Existem ainda alguns operadores que podem ser usados nos parametros, como é o caso do '+'.

fatorial :: Int -> Int
fatorial 1 = 1
fatorial (n+1) = (n+1) * (fatorial n)

Um outro exemplo interessante é a função 'e lógico', que é definida para bool's, por exemplo:

and :: Bool -> Bool -> Bool
and True True = True
and True False = False
and False True = False
and False False = False

Notem que em apenas um ramo da função retornamos True, de resto retornamos SEMPRE False.

Isso pode ser escrito usando um underline, '_', por exemplo:

and :: Bool -> Bool -> Bool
and True True = True
and _ _ = False
E esse underline pode ser lido como 'qualquer coisa'.

Essa função é interpretada como: "Retorna 'True' se o input for 'True True', se for qualquer outra coisa retorna 'False'"

 

Atenção!!!

Se definissemos a função da seguinte forma:

and :: Bool -> Bool -> Bool
and _ _ = False
and True True = True
Estaria completamente errado!

O Haskell checa os ramos na ordem em que foram definidos, e executa o primeiro que satisfizer o padrão.

Nesse caso, o primeiro ramo satisfaz QUALQUER padrão, portanto é sempre executado.

 

nota

Agora que estamos falando em pattern matching, vou vos mostrar mais um tipo de dado em Haskell.

Os n-úplos.

Que não são nada mais do que os pares, ternos, quadruplos, quintuplos, etc...

Para declarar um par de inteiros fazemos:

(Int, Int)
Para declarar um par de um float e um par de inteiros fazemos:

(Float, (Int, Int))

Se temos dois inteiros, por exemplo 5 e 7, e queremos colocálos num par é mesmo MUITO fácil:

(5, 7)
É só escrever os pareteses e separá-los com uma vírgula.

 

Os pares em Haskell podem ser dissecados com o pattern matching,

Vamos imaginar, por exemplo, uma função que recebe um par e retorna um Bool.

Nesse par temos uma lista de números e um número.

funcao :: ([Int], Int) -> Bool
funcao par = .....
E teríamos que utilizar as funções fst, e snd para pegar o primeiro e o segundo elemento do par, respectivamente.

Mas, o pattern matching nos salva!

funcao :: ([Int], Int) -> Bool
funcao (lista, n) = ......
E notem que o haskell separou os items do par para nós.

Onde 'lista' é do tipo [int] e 'n' é do tipo Int.

Falando em Haskell, 'lista :: [int]' e 'n :: Int'

 

As listas também podem ser dissecadas.

Lembram-se do operador ':'??

O ':' insere um elemento no início de uma lista, logo, a sua assinatura é:

(:) :: a -> [a] -> [a]
E ele pode ser usado no pattern matching.

Quando recebemos uma lista, podemos dividir ela no primeiro elemento e o resto da lisa, por exemplo:

funcao2 :: [Int] -> Int
funcao2 (h:t) = ....
Onde h é o primeiro elemento, e 'h :: Int', e t é o resto da lista, 't :: [int]'

 

Podemos também colocar outro ramo, definindo o funcionamento quando a lista é vazia:

funcao2 :: [Int] -> Int
funcao2 [] = .....
funcao2 (h:t) = ....

Bom, por hoje é só!

Detalhe: Notei que ninguém respondeu o tópico da última aula, o tópico está aqui para tirar dúvidas.

Se não entenderam algo, por favor falem!

=D

 

Alguns exercícios:

//(a) qual o tipo de 'h' e 't'?
fA :: [Int] -> (Bool, Int)
fA (h:t) = ....


//(B) qual o tipo de 'n', 'x', 'y', e 'z'?
fB :: (Int, Int, Float) -> [Bool] -> Int
fB (x, y, z) n = .....

//(c) qual o tipo de 'p' e 'ps'?
fC :: [(Int, Int)] -> Bool
fC (p:ps) = ....

//(d) qual o tipo de 'p1', 'p2', e 'resto' ??
fD :: [(Int, Float)] -> Bool
fD ((p1, p2):resto) = .....

//(e) qual o tipo de 'x', 'xs' e 'y' ???
fE :: [a] -> [b] -> [(a, B)]
fE (x:xs) y = ....

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.