Aula 2 - haskell super básico

livro texto capitulos: 2 (tipos, if, funções e listas) , 4 (pattern matching e guards) e 5 (recursão)

haskell online

Funções

Define a função usando nomes, parametros e o corpo da função depois do =

Sintaxe:

duplica x = 2*x

duplica 56

soma a b = a + b

soma 2 (duplica 5)

if then else

O if define que expressão retornar, e tem sempre um else

maior a b = if a>b 
              then a 
              else b 

maior 5 8

if é uma expressão que retorna algo

(if x>100 then x else 2*x) + 78

listas

Sintaxe como em python mas só de dados do mesmo tipo

[4,5,3,2,3,7]

[] <-- lista vazia

Função head e tail para obter o 1o elemento e o resto da lista

head [14,5,16]
14

tail [14,5,16]
[5,16]

tail [1]
[]

tail []
Exception: Prelude.tail: empty list

Recursão - e apenas recursão

tamanho de uma lista

conta lista = if lista == [] 
           then 0
           else (1 + tamanho (tail lista))

quantas vezes x aparece na lista

vezes x lista = if lista == [] 
               then 0 
               else if head lista == x then 1 + vezes x (tail lista) 
                                   else vezes x (tail lista)

ou usando if como expressão

vezes x li  = if li == [] 
               then 0 
               else (if head li == x then 1 else 0) + vezes x (tail li)

Pattern matching

Funções podem ser escritas como um conjunto de regras que especificam os formatos dos argumentos.

(x:xs) quebra a lista no head que é colocado em x e no tail que é colocado no xs A lista vazia não pode ser quebrada dessa forma

[] é equivalente a testar se o valor recebido é a lista vazia.

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

vezes _ []  = 0
vezes x (a:as) = (if x==a then 1 else 0) + vezes x as

_ é uma variavel anonima que não pode ser usada (como em python)

Cuidado, não da para testar igualdade entre valores no pattern matching. O codigo abaixo nao dá certo:

---- ERRADO ERRADO -----
vezes _ [] = 0
vezes a (a:as) = 1 + vezes a as   <=== NAO FUNCIONA
vezes x (a:as) = vezes x as

++ concatena 2 listas

remove _ [] = []
remove x (a:as) = if x == a
                     then remove x as 
                     else [a] ++ (remove x as)

o : pode ser usado para construir listas

remove _  [] = []
remove x (a:as) = if x == a
                     then remove x as 
                     else a:(remove x as) 

o “:” tem baixa prioridade - é feito “depois”. O parenteses em torno de remove x (a:as)= é preciso pois sem ele o haskell entenderia (remove x a) : as = que é um erro de sintaxe.

Mas na ultima linha acima, a chamada da função tem maior prioridade. assim isso poderia ser escrito como

remove _  [] = []
remove x (a:as) = if x == a
                     then remove x as 
                     else a : remove x as 

Mas use parenteses se vc estiver inseguro/insegura.

let in

let … in - define as variáveis e funções locais antes da chamada/expressão principal

maior [x] = x
maior (x:xs) = let
         mm = maior xs
     in if x>mm then x else mm 

Proxima aula

e

Exercicios

Fazer os exercícios usando head tail : ++ mod (modulo), let e pattern matching

Alguns são bem dificies de fazer usando apenas os conceitos da aula 1!

range_rev n = if n==1
        then [1]
        else n:range_rev (n-1)
ou

range_rev' 1 = []
range_rev' n = n: range_rev (n-1)
-- tradicional fold right
rev1 [] = []
rev1 (x:xs) = rev1 xs ++ [x]


-- com acumulador do trabalho anterior fold left
rev lista = rev2 lista []
rev2 [] acc = acc
rev2 (x:xs) acc = rev2 xs (x:acc)
intercala1 [1,2,3] [4,5,6,7,8]
 ==> [1,4,2,5,3,6]
intercala2 [1,2,3] [4,5,6,7,8]
 ==>  [1,4,2,5,3,6,7,8]
shiftr [1,2,3,4]
 ==> [4,1,2,3]
remove1 4 [2,3,4,5,4,3,2,1]
==> [2,3,5,4,3,2,1]
removeall 4 [2,3,4,5,4,3,2,1,4,4,3]
==> [2,3,5,3,2,1,3]
removen 4 2 [2,3,4,5,4,3,2,1,4,4,3]
==> [2,3,5,3,2,1,4,4,3]
troca1 8 10 [2,4,6,8,11,12]
==> [2,4,6,10,11, 12]