O documento discute como a programação funcional pode ser uma ferramenta poderosa para lidar com a complexidade de programas. Apresenta abstrações funcionais como monóides e mônadas que permitem dividir programas em partes menores e compô-los de forma previsível, levando à corretude por construção. Também discute como essas abstrações matemáticas promovem maior abstração no desenvolvimento de software.
5. Arthur Xavier
Estudante de Ciência da Computação;
Apaixonado por programação funcional;
Membro ativo da comunidade FP;
Desenvolvendo com Phil Freeman uma formalização
de interfaces de usuário declarativas com Comonads;
6. OU COMO
PROGRAMAÇÃO FUNCIONAL É UMA ÓTIMA FERRAMENTA PARA CONTROLE
DE COMPLEXIDADE.
PROGRAMAS E FUNÇÕES
SOBRE
PENSANDO EM ABSTRAÇÃO,
7. Outline
Por que programação funcional;
Abstrações funcionais;
Complexidade sem dificuldade:
1. Monóides;
2. Mônadas.
10. comando1();
comando2(); // mudança de estado
variável = comando3(); // estado privado
if (variável.atributo)
exceção!
envia_email(); // mudança de estado
lança_míssil();
// return variável;
13. Linguagens convencionais
Semântica sequencial de transições de estado;
Divisão entre mundo das expressões vs. comandos;
Dificuldade de combinar programas;
Ausência de propriedades matemáticas.
31. Conjunto S com uma operação binária •, tal que
1. ∀a,b ∈ S : a•b ∈ S. (fechamento)
2. ∀a,b,c ∈ S : (a•b)•c = a•(b•c). (associatividade)
3. ∃e ∈ S : ∀a ∈ S : e•a = a•e = a. (identidade)
49. HASKELL
data Add = Add Int
instance Monoid Add where
Add a <> Add b = Add (a + b)
mempty = Add 0
…
data Mult = Mult Int
instance Monoid Mult where
Mult a <> Mult b = Mult (a * b)
mempty = Mult 1
50. HASKELL
foldMap :: Monoid m => (a -> m) -> [a] -> m
foldMap f [] = mempty
foldMap f (a:as) = f a <> foldMap f as
55. HASKELL
data Builder a = Builder (a -> a)
instance Monoid (Builder a) where
Builder f <> Builder g = Builder (f . g)
mempty = Builder id
build :: a -> Builder a -> a
build def (Builder builder) = builder def
57. Disjunção de predicados;
Conjunção de predicados;
Conjuntos com união;
Composição de opções;
Combinação de regras;
Interseção de formas bidimensionais;
Funções que retornam monóides;
Combinação de máquinas de estado;
61. HASKELL
add1 :: Int -> (Int, String)
add1 x = (x + 1, "+1")
mul3 :: Int -> (Int, String)
mul3 x = (x * 3, "*3")
-- deseja-se
add1 30 ?? mul3 ?? add1 = (94, "+1*3+1")
-- mas o que é (??)
62. HASKELL
add1 :: Int -> (Int, String)
add1 x = (x + 1, "+1")
mul3 :: Int -> (Int, String)
mul3 x = (x * 3, "*3")
-- ou ainda
do
x <- add1 30
y <- mul3 x
add1 y
63. HASKELL
add1 :: Int -> (Int, String)
add1 x = (x + 1, "+1")
mul3 :: Int -> (Int, String)
mul3 x = (x * 3, "*3")
-- deseja-se
add1 30 ?? mul3 ?? add1 = (94, "+1*3+1")
-- mas o que é (??)
75. HASKELL
data Writer a = Writer (a, String)
instance Monad Writer where
pure a = Writer (a, "")
Writer (a, s) >>= f = Writer (b, s ++ s2)
where
Writer (b, s2) = f a
77. HASKELL
data Writer t a = Writer (a, t)
instance Monoid t => Monad (Writer t) where
pure a = Writer (a, mempty)
Writer (a, t) >>= f = Writer (b, t <> t2)
where
Writer (b, t2) = f a
78. HASKELL
add1 :: Int -> Writer String Int
add1 x = Writer (x + 1, "+1")
mul3 :: Int -> Writer String Int
mul3 x = Writer (x * 3, "*3")
add1 30 >>= mul3 >>= add1 = (94, "+1*3+1")
79. HASKELL
add1 :: Int -> Writer String Int
add1 x = Writer (x + 1, "+1")
mul3 :: Int -> Writer String Int
mul3 x = Writer (x * 3, "*3")
do
x <- add1 30
y <- mul3 x
add1 y
80. HASKELL
tell :: Monoid t => t -> Writer t ()
tell t = Writer ((), t)
add1 x = do { tell "+1"; pure (x + 1) }
mul3 x = do { tell "*3"; pure (x * 3) }
do
x <- add1 30
y <- mul3 x
add1 y
82. HASKELL
data State s a = State (s -> (a, s))
instance Monad (State s) where …
put :: s -> State s ()
put s = _ -> ((), s)
get :: State s s
get = s -> (s, s)
modify :: (s -> s) -> State s ()
modify f = s -> ((), f s)
83. HASKELL
put :: s -> State s ()
get :: State s s
modify :: (s -> s) -> State s ()
…
add1 x = do
modify (log -> log <> "+1")
pure (x + 1)
mul3 x = do
modify (log -> log <> "*3")
pure (x * 3)
85. HASKELL
data Maybe a = Nothing | Just a
instance Monad Maybe where …
head :: [a] -> Maybe a
…
tryGetLastPhoto username = do
user <- tryGetUser username
photos <- tryGetPhotos user
head photos