livro texto (cap 6)
Para o compilado
main = do
print $ sua funcao com argumentos
toda funçao em Haskell é “na verdade” uma funçao de 1 argumento (que pode retornar funções)
max 4 5
(max 4) 5
let w = max 4
w 3
w 5
:t w
w :: (Ord a, Num a) => a -> a
w
precisa receber um Ord por causa do max
mas também um Num por causa do 4
Prelude> :t max
max :: Ord a => a -> a -> a
Na interpretação da aula passada, max
é uma função de 2 argumentos a -> a
que retorna um a
(e o a
tem que satisfazer o Ord)
Na interpretação de currying o tipo de max
é na verdade
max :: Ord a => a -> (a -> a)
ou seja max
recebe um a
e retorna uma função que esta esperando um a
para retornar um a
(que é a função armazenada em w
)
Veja que nos podemos escrver a função w como
w x = max 4 x
w = max 4
essa segunda versão/notação é chamada de point-free style
Funções infixas (+
, etc) para funções unárias:
(8+)
:t (+8)
f1 = (<5)
:t f1
f2 = (5>)
:t f2
maiuscula = (`elem` ['A'..'Z'])
(<5)
(expressoes infixas incompletas) são chamados sessions
aplica2 f x = f (f x)
:t aplica2
aplica2 :: (t -> t) -> t -> t
zipWith' f [] _ = []
zipWith' f _ [] = []
zipWith' f (a:as) (b:bs) = f a b : (zipWith' f as bs)
zipWith' (+) [1..5] [1000..1004]
flip' f = g
where g x y = f y x
zipWith' (flip' div) [2,2,2,1] [10,8,4,0]
flip
e zipWith
já estão definidas
$
aplica2 f x = f (f x)
aplica2 f x = f $ f x
:t aplica2
o $
é um abre parênteses com o fecha parênteses implicito no fim do comando.
o $
é um pipe f (g (h x)) = f $ g $ h x
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (a:as) = f a : (map f as)
map (5-) [10,8..0]
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter p (x:xs)
| p x = x : (filter p xs)
| otherwise = filter p xs
impar x = x `mod` 2 == 1
filter impar [1,5,4,3,6,7,8]
map e filter ja estao definidas
Num certo sentido, o list comprehension combina o map e o filter
map f $ filter p lista
[ f x | x <- lista, p x]
Cria funções sem nomes
\ argumentos -> corpo
filter (\ x -> x `mod` 2 == 1) [1,5,4,3,6,7,8]
zipWith (\a b -> if a>b then a+3 else b-1) [1,2,3,4] [5,4,3,2]
foldr
é a recursao tradicional (o resultado vem da direita - fim da lista)
soma [] = 0
soma (x:xs) = x + (soma xs)
-- foldr combina valor-inicial lista
foldr _ init [] = init
foldr f init (x:xs) = f x (foldr f init xs)
soma l = foldr (+) 0 l
soma = foldr (+) 0
:t foldr
veja o tipo da funçao de combinação
foldl
é a recursao com acumulador, que o resultado vem da esquerda - do começo da lista
-- foldl combina valor-inicial lista
somaacc acc [] = acc
somaacc acc (x:cs) = somaacc (acc+x) xs
foldl _ acc [] = acc
foldl f acc (x:xs) = foldl f (f acc x) xs
somaacc l = foldl (+) 0 l
somaacc = foldl (+) 0
:t foldl
veja o tipo da funçao de combinação
foldr1
é o foldr
onde o valor inicial é o ultimo elemento
foldl1
é o foldl
onde o valor inicial do acumulador é o primeiro elemento
minimo = foldl1 (\a b -> if a<b then a else b)
minimo = foldl1 min
produto = foldr1 (*)
produtoescalar l1 l2 = foldr1 (+) $ zipWith (*) l1 l2
produtoescalar = foldr1 (+) $ zipWith (*)
(map, filter, fold)
1 2 3
4 5 6
7 8 9
0 0 -1
[[1,2,3],[4,5,6],[7,8,9],[0,0,-1]]
implemente transposta
que transpoe uma matrix
matmul
que dado duas matrizes de formatos apropriados multiplica-as.