Ir para conteúdo

POWERED BY:

Arquivado

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

VictorCacciari

[Haskell Aula 04] Mais Recursividade

Recommended Posts

Aula 04 - Variáveis e mais recursividade

 

Olá Pessoal, desculpem a demora, mas estamos de volta!

Hoje já vamos começar a fazer coisas mais úteis para o 'projeto' final.

 

Variáveis

Em Haskell, podemos trabalhar com uma espécie de variáveis, a forma mais fácil de explicar é com exemplos.

f :: Int -> Int -> Int
f a b = let c = a + b
          in c*2

Ou

 

f :: Int -> Int -> Int
f a b = c * 2
         where c = a + b

Também é válido.

A diferença entre o 'let' e o 'where' é o escopo.

O let é mais restrito, e as coisas ficam apenas visíveis naquele ramo, já o where fornece informação para todas as condições.

Por exemplo (nota: '++' concatena listas):

g :: Int -> [Int] -> Bool
g a l | a == 0 = aux l
      | otherwise = aux (l ++ [0])
          where
	      aux :: [a] -> Bool
	      aux n = faz_qualquer_coisa_com_n

A função aux está visível tanto para o sub-ramo onde a é zero, quanto para o outro.

A declaração com lets não permite isso.

 

Outro recurso interessante é que é possível fazer pattern matching com 'let's e 'where's

Por exemplo, uma possível definição para a função unzip, que pega numa lista com pares e retorna um par de listas:

unzip :: [(a, B)] -> ([a], [b])
unzip [] = [] // caso elementar
unzip ((e1, e2):t) = let (l1, l2) = unzip t // Nós vamos primeiro fazer unzip no resto da lista
                       in (e1:l1, e2:l2) //E apenas quando toda a lista ja estiver pronta, colocamos os elementos nas listas corretas.

Outro exemplo, a função splitAt, que divide uma lista numa dada posição e retorna um par com duas listas:

splitAt :: Int -> [a] -> ([a], [a])
splitAt 0 a = ([], a) //dividir a lista na posição zero
splitAt n (h:t) = let (l1, l2) = splitAt (n-1) t
			in (h:l1, l2)

EXERCÍCIOS:

//Defina a função div, que divide dois números inteiros, usando recursividade
div :: Int -> Int -> Int

//Defina a função mod, que retorna o modulo de dois números inteiros, usando recursividade
mod :: Int -> Int -> Int

//A função divMod pode ser definida da seguinte forma:
divMod :: Int -> Int -> (Int, Int)
divMod a b = (div a b, mod a B)

//Apresente uma definição recursiva para a função divMod

//defina a função insere, que recebe um inteiro e insere-o numa lista ordenada, mantendo-a ordenada.
insere :: Int -> [Int] -> [Int]

//defina a função merge, que recebe duas listas ordenadas e retorna uma lista ordenada, dica: use a função insere
merge :: [Int] -> [Int] -> [Int]

//defina uma função ordena, que ordena uma lista
ordena :: [Int] -> [Int]

//defina a função unzip3, que faz o mesmo que a função unzip, mas com ternos
unzip3 :: [(a, b, c)] -> ([a], [b], [c])

Pessoal, é importante entender muito bem esses conceitos, para partirmos para estruturas de dados e tipos abstratos de dados.

Aconselho que façam os exercícios e postem dúvidas, busquem mais exercícios na internet para resolvê-los.

 

ATENÇÃO: as funções div, mod, divMod e unzip3 já estão definidas no Haskell, utilizem outros nomes.

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.