VictorCacciari 42 Denunciar post Postado Janeiro 10, 2010 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