Escolar Documentos
Profissional Documentos
Cultura Documentos
Funcional
int total = 0;
for (int i = 1; i <= 100; i++)
total = total + i;
s1_100 :: Integer
s1_100 = sum [1..100]
• constantes
• operadores
• aplicação de funções
• (parênteses)
Expressões
Constantes:
-3.459
True
'a'
"hello"
[1,2,4,9]
Aplicação de funções:
even 47
twice (-2)
Operadores
. Composição de funções
*, /, ^ multip, divisão, potência
:, ++ composição de listas,
concatenação
==,/=,<=,... igual, desigual, comparação
&& E
|| OU
Definições
pi = 3.14159
circumf r = 2 * pi * r
O que é um tipo?
Bool Boleanos
Char Caracteres
Int Inteiros de 32-bits
Integer Inteiros de tam ilimitado
Float Ponto flutuante
Double Dupla precisão
Tipos em Haskell
Toda expressão em Haskell deve ter um tipo
associado
Tipos podem ser explícitos ou inferidos
sum :: Float -> Float -> Float
sum x y = x + y
Matemática Haskell
f (x) f x
f (x,y) f xy
f (g(x)) f (g x)
f (x, g(y)) f x (g y)
f (x) g(y) f x*gy
f(a,b) + c d f ab+c*d
• construtores:
1 : 1 : 2 : 3 : 5 : 8 : []
• “colchetes":
[1, 1, 2, 3, 5, 8]
Comprimento:
Main> length [1, 1, 2, 3, 5, 8]
6
Main> length ""
0
Concatenação
Main> [1, 1, 2, 3] ++ [5, 8]
[1, 1, 2, 3, 5, 8]
Main> [] ++ [1] ++ [2]
[1,2]
Funções em Listas
Heads e tails
Main> head [1, 2, 4]
1
Main> tail [1, 2, 4]
[2,4]
Main> head []
ERROR: ...
take 4 “aeroporto"
“aero“
drop 2 ['i','n','t','e','n','t']
"tent"
reverse 'p':'o':'o':'l':[]
"loop"
-- zip :: [a] -> [b] -> [(a,b)]
zip [1,2,3,4,5] "cat"
[(1,'c'),(2,'a'),(3,'t')]
Tipos Parametrizados
length [] = 0
length (x : xs) = 1 + length xs
Comportamento Situacional em
Funções sobre Listas
zip [] ss = []
zip is [] = []
zip (i:is) (s:ss) = (i,s) : zip is ss
Mais “Pattern Matching”
concat [] = [] --- = “”
length [] = 0
length (x : xs) = 1 + length xs
length (1 : 2 : 4 : [])
⇒
Avaliação de Funções Recursivas
length [] = 0
length (x : xs) = 1 + length xs
length (1 : 2 : 4 : [])
⇒ { x ← 1 , xs ← 2 : 4 : [] }
Avaliação de Funções Recursivas
length [] = 0
length (x : xs) = 1 + length xs
length (1 : 2 : 4 : [])
⇒ { x ← 1 , xs ← 2 : 4 : [] }
1 + length (2 : 4 : [])
Avaliação de Funções Recursivas
length [] = 0
length (x : xs) = 1 + length xs
length (1 : 2 : 4 : [])
⇒ { x ← 1 , xs ← 2 : 4 : [] }
1 + length (2 : 4 : [])
⇒ { x ← 2 , xs ← 4 : [] }
Avaliação de Funções Recursivas
length [] = 0
length (x : xs) = 1 + length xs
length (1 : 2 : 4 : [])
⇒ { x ← 1 , xs ← 2 : 4 : [] }
1 + length (2 : 4 : [])
⇒ { x ← 2 , xs ← 4 : [] }
1 + 1 + length (4 : [])
⇒
Avaliação de Funções Recursivas
length [] = 0
length (x : xs) = 1 + length xs
length (1 : 2 : 4 : [])
⇒ { x ← 1 , xs ← 2 : 4 : [] }
1 + length (2 : 4 : [])
⇒ { x ← 2 , xs ← 4 : [] }
1 + 1 + length (4 : [])
⇒ { x ← 4 , xs ← [] }
1 + 1 + 1 + length []
⇒
Avaliação de Funções Recursivas
length [] = 0
length (x : xs) = 1 + (length xs)
length (1 : 2 : 4 : [])
⇒ { x ← 1 , xs ← 2 : 4 : [] }
1 + length (2 : 4 : [])
⇒ { x ← 2 , xs ← 4 : [] }
1 + 1 + length (4 : [])
⇒ { x ← 4 , xs ← [] }
1 + 1 + 1 + length []
⇒ {}
Avaliação de Funções Recursivas
length [] = 0
length (x : xs) = 1 + (length xs)
length (1 : 2 : 4 : [])
⇒ { x ← 1 , xs ← 2 : 4 : [] }
1 + length (2 : 4 : [])
⇒ { x ← 2 , xs ← 4 : [] }
1 + 1 + length (4 : [])
⇒ { x ← 4 , xs ← [] }
1 + 1 + 1 + length []
⇒ {}
1+1+1+0
Conjuntos matemáticos como
Listas
Um dos mais poderosos conceitos de Haskell é o
percorrimento automático de uma lista
Main> xs = [1,2,3,4,5,6]
[2,4,6,8,10,12].
Percorrimento de Listas
Elementos do percorrimento de uma lista
result = [ <corpo> | <seletor>, <filtro>]
que é equivalente a:
maxof3 x y z = maxof2 (maxof2 x y) z
Quicksort em Haskell
qsort [] = []
qs [3,2,4,1,5]
[1,2,3,4,5]
Sequência de Fibonnacci
fib n = fib1
where
(fib1, fib2) = fibs n
fst :: (a,b) → a
head :: [a] → a
Main> 1 + 2
3
(+) :: a → a → a
(+) :: Num a ⇒ a → a → a
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
Classes Básicas em Haskell
Sobrecarga
Um único nome indica muitas funções
(+) engloba adição de inteiros e de reais.
Parametrização Implícita
Quando instanciamos um tipo nosso como derivado de
uma classe, herdamos a assinatura definida por seus
métodos
Todos os (+) tem de ter assinatura a->a->a
A instanciação pode ser parcial
Classes em Haskell x Herança em
C++
Herança em C++
Compartilha interface e implementação (estruturas de
dados) entre classe base e classe derivada
twice :: (a → a) → a → a
twice f x = f (f x)
Map
map f [] = []
map f (x : xs) = (f x) : map f xs
map f xs = [f x | x ← xs]
Map
(+ m) n = m + n
Uso de Map com Avaliação Parcial
incAll = map (1 +)
class func{
public: void operator() (int obj);
}
vector<int> col;
for_each(col.begin(), col.end(), func);
filter p xs = [x | x ← xs, p x]
filter p [] = []
filter p (x : xs)
|px = x : filter p xs
| otherwise = filter p xs
Padrões de Recursão em Listas
f [] =v
f (x:xs) = x ⊕ f xs
sum [] =0
sum (x:xs) = x + sum xs
product [] =1
product (x:xs) = x * product xs
and [] = True
and (x:xs) = x && and xs
Função Foldr
foldr f v [] =v
foldr f v (x:xs) =
f x (foldr f v xs)
Exemplos
Escreva um função produto que multiplica
todos os elementos de uma lista
product [] = 1
product (n : ns) = n * product ns
flatten [] = []
flatten (l : ls) = l ++ flatten ls
flatten = foldr [] ++
Mais exemplos de foldr
reverse (1 : (2 : []))
⇒
swap 1 (swap 2 [])
⇒
(swap 2 []) ++ [1]
⇒
([] ++ [2]) ++ [1]
Reverse pode ser mais eficiente
reverse = rev []
where
rev l [] = l
rev l (x:xs) = rev (x:l) xs
Reverse pode ser mais eficiente
reverse = rev []
where
rev l [] = l
rev l (x:xs) = rev (x:l) xs
rev [] (1 : (2 : []))
⇒
rev (1:[]) (2 : [])
Reverse pode ser mais eficiente
reverse = rev []
where
rev l [] = l
rev l (x:xs) = rev (x:l) xs
rev [] (1 : (2 : []))
⇒
rev (1:[]) (2 : [])
⇒
rev (2:(1:[])) []
Reverse pode ser mais eficiente
reverse = rev []
where
rev l [] = l
rev l (x:xs) = rev (x:l) xs
rev [] (1 : (2 : []))
⇒
rev (1:[]) (2 : [])
⇒
rev (2:(1:[])) []
⇒
2 : (1 : [])
Função foldl (“fold left”)
foldl f e [] = e
foldl f e (x : xs) = foldl f (f e x) xs
Usando foldl
compose f g x = f (g x)
(f . g) x = f (g x)
-- tOrd is ["foo","bar","fubar","bat","baz"]
tOrd = qsortF tailComp myWords
-- hOrd is ["bar","bat","baz","foo","fubar"]
hOrd = qsortF (<) myWords
Usando notação “Lambda”
Passar funções para outras funções é apenas
parte do poder de Haskell
slope f =
(\x →(f(x+dta x) - f(x-dta x))/(2*dta x))
where
dta x = x / 10000
Tipos Definidos pelo
Usuário
Declaração de Novos Tipos de
Dados
data CardinalPoint
= North | East | South | West
deriving (Eq, Show)
Main> East
East
Main> East == West
False
Tipos Enumeráveis
-- Haskell
data Point = Point (Double,Double)
deriving (Show)
Construtores
Para criar instâncias do tipo, temos de usar o
construtor
-- Haskell
data Point = Pt (Double,Double)
deriving (Show)
Succ Zero
---corresponde ao número 3
Tipos Recursivos – Comparação
com C++
data Nat = Zero | Succ Nat
struct Nat {
Int zero;
Nat* succ;
}
Leaf Fork
2 Fork Leaf
Leaf Leaf 9
1 5
Leaf Fork
2 Fork Leaf
Leaf Leaf 9
1 5
Val *
2 + Val
Value Value 9
1 5
Expressões Aritméticas
-- 1 + (2+5)*9
Funções sobre Expressões
Aritméticas
eval (Val n) = n
eval (Add x y) = x + y
eval (Mul x y) = x * y
Avaliação Preguiçosa
e Listas Infinitas
Avaliação Preguiçosa (“Lazy
evaluation”)
Em C++, a avaliação de expressões é estrita e
imediata
Se escrevemos x = y + z , o compilador avalia a expressão
imediatamente
Main> [0..7]
[0,1,2,3,4,5,6,7]
Main> [1..]
[1,2,3,4,5,6,7, ...
...
2918,2919,291<<not enough heap space -- task
abandoned>>
Listas Infinita
Main> natsfrom 0
[0,1,2,3,....
Crivo de Eratóstenes
O crivo
• Começe em 2
• Delete todos os múltiplos do primeiro
numéro do restante da lista
• Repita
Crivo de Eratóstenes
-- Crivo de Eratóstenes
primes = crivo [2 .. ]
-- este é o crivo
crivo(x:xs) =
x: crivo [y | y <- xs, rem y x /=0]
Um programa
em Haskell O objetivo de
consiste num executar qqer
conjunto de programa é ter
funções, sem Tensão algum efeito
efeitos colateral
colaterais
A Solução
IO a
result::a
IO a
World in World out
O conceito de ação
Um valor do tipo (IO t) é uma ação que,
quando realizada, pode fazer alguma
forma de IO antes de devolver um
resultado do tipo t.
type IO a = World -> (a, World)
getChar :: IO Char
Ações Primitivas
putChar :: Char → IO ()
return :: a → IO a
Seqüência de Ações
Por exemplo:
getTwo :: IO (Char,Char)
getTwo = do x ← getChar
y ← getChar
return (x,y)
Sequencia de Ações
getLine :: IO [Char]
getLine = do { x ← getChar
if x == '\n' then
return []
else
do { xs ← getLine
return (x:xs) }
}
Ações em Haskell
Escrever uma palavra na tela:
putStr :: String → IO ()
putStr [] = return ()
putStr (x:xs) = do putChar x
putStr xs
putStrLn :: String → IO ()
putStrLn xs = do putStr xs
putChar '\n'
Exemplo
strlen :: IO ()
strlen = do putStr "Enter a string: "
xs ← getLine
putStr "The string has "
putStr (show (length xs))
putStrLn " characters"
Examplos
getChar :: IO Char
getLine :: IO String
Char Char ()
getChar putChar
getChar :: IO Char
putChar :: Char → IO () O “main” é do
tipo IO ()
main :: IO ()
main = putChar ‘x’
O combinador (>>=)
(>>=) :: IO a → (a → IO b) → IO b
()
Char
getChar putChar
echoDup :: IO ()
echoDup = getChar >>= (\c →
putChar c >>= (\() →
putChar c))
echoDup :: IO ()
echoDup = getChar >>= \c ->
putChar c >>
putChar c
(>>) :: IO a → IO b → IO b
m >> n = m >>= (\x → n)
O combinador return
getTwoChars :: IO (Char,Char)
getTwoChars = getChar >>= \c1 ->
getChar >>= \c2 ->
return (c1,c2)
return :: a → IO a
return
Conveniência de notação (uso de
“do”)
getTwoChars :: IO (Char,Char)
getTwoChars = do { c1 <- getChar ;
c2 <- getChar ;
return (c1,c2) }
do {x←e; s} = e >>= \x → do { s }
do {e; s} = e >> do { s }
do { e } = e
(>>=) :: IO a → (a → IO b) → IO b
(>>) :: IO a → IO b → IO b
GetLine
getLine :: IO [Char]
getLine = do { c <- getChar;
if c == ‘\n’ then
return []
else do { cs <- getLine;
return (c:cs) }
}
forever :: IO () -> IO ()
forever a = a >> forever a
(>>) :: IO a → IO b → IO b
m >> n = m >>= (\x → n)
for :: [a] → (a → IO b) → IO ()
for xs fa = sequence (map fa xs) >>
return ()
Mônadas
return :: a → m a
(>>==) :: m a → (a → m b) → m b -- bind
(>>) :: m a → m b → m b -- seq
fail :: String → m a
Mônadas
class Monad m where
return :: a → m a
(>>==) :: m a → (a → m b) → m b -- bind
(>>) :: m a → m b → m b -- seq
fail :: String → m a
-- definicoes basicas
p >> q = p >>= \_ → q
fail s = error s
Monads
return x >>= f = fx
m >>= return = m
m1 >>= (λ x.m2 >>= (λ y.m3))
= (m1 >>= (λ x.m2)) >>= (λ y.m3)
return :: a → IO a
returnInv :: IO a → a
returnInv :: IO a → a
returnInv :: IO a → a
unsafePerformIO:: IO a → a
Organização de
Programas
Leiaute