Programação funcional tipada
Uma introdução
meu nome é Arthur Xavier
Oi,
Sou estudante de Ciência da Computação
e apaixonado por Programação Funcional
@arthurxavierx
@arthur-xavier
Maior previsibilidade.
Melhor testabilidade.
Facilidade de raciocínio.
Simplicidade.
Ajuda a evitar uma grande classe de bugs.
Por quê programação funcional?
Não é somente programar com funções.
É um paradigma de programação declarativo.
Modela computações como o resultado da avaliação e composição de funções.
Evita dados mutáveis e efeitos colaterais.
Mas o que é programação funcional?
function squareArrayImperative(arr) {
let result = [];
for (let i = 0; i < arr.length; i++) {
result.push(arr[i] ** 2);
}
return result;
}
Programação imperativa
const squareArrayDeclarative = arr => arr.map(x => x ** 2);
Programação declarativa
squareList : List Int -> List Int
squareList xs = List.map (x -> x^2) xs
(Elm) Programação declarativa
Linguagem de programação para a criação de interfaces web declarativas.
Foco na usabilidade do desenvolvedor, performance e resiliência.
Elm
Fortemente tipada e funcional pura.
Na prática, aplicações escritas em Elm não produzem exceções de runtime.
Elm
Uma função é uma expressão.
Mapeia elementos de um domínio em elementos de um contradomínio.
Funções
Função
Função
f : ℤ → ℕ = x ↦ |x|
(Elm) Função
f : Int -> Int
f x = abs x
Funções
Seja um conjunto tal que:
ε ∈ ,
∀ x ∈ ℤ, ∀ α ∈ , x • α ∈ .
Então
squareL : → = α ↦
ε se α = ε
x² • squareL(β) se α = x • β
sumL : → ℤ = α ↦
0 se α = ε
x + sumL(β) se α = x • β
(Elm) Funções
squareList : List Int -> List Int
squareList l =
case l of
[] -> []
x :: xs -> x^2 :: squareList xs
sumList : List Int -> Int
sumList l =
case l of
[] -> 0
x :: xs -> x + sumList xs
Toda função é pura.
Funções impuras são chamadas de procedimentos, rotinasou subrotinas.
Funções puras
Uma função pura é uma função que sempre produz o mesmo resultado quando são
passados os mesmos argumentos, e que não produz efeitos colaterais observáveis.
Funções puras
Efeitos colaterais
“Uma função ou expressão produz efeitos colaterais se ela modifica algum estado
fora de seu escopo ou realiza alguma interação observável com as funções que a
chamaram ou com o mundo externo.”
– Wikipedia
Função impura
function append(x) {
this.array.push(x);
}
Função impura
function appendToArray(array, x) {
array.push(x);
}
Função pura
function appendToArray(array, x) {
return [ ...array, x ];
}
(Elm) Função pura
appendToList : List Int -> Int -> List Int
appendToList list x = list ++ [x]
Função impura
function sumOfSquares(array) {
let result = 0;
for (let x in array) {
result += x*x;
}
console.log(result);
};
Função pura
const square = x => x*x;
const add = (a, b) => a + b;
function sumOfSquares(array) {
return array
.map(square)
.reduce(add, 0);
}
console.log(sumOfSquares([2, 3, 5]));
(Elm) Função pura
sumOfSquares : List Int -> Int
sumOfSquares list =
let
square x = x*x
in
List.foldl (+) 0 (List.map square list)
-- cadê o console.log??
Como
programação funcional pura
pode ser útil
se não tem efeitos colaterais?
Abestado,
tem efeitos colaterais sim,
mas são.
representados de forma diferente.
Linguagens funcionais implementam funções de primeira classe.
Funções em linguagens funcionais são valores.
Funções podem ser passadas como argumentos para outras funções.
Funções podem ser valores de retorno de outras funções.
Funções de primeira classe
São funções que recebem outras funções como argumento.
map
reduce / fold
filter
Funções de alta ordem
Funções de alta ordem
sumOfSquares : List Int -> List Int
sumOfSquares list =
let
square x = x*x
in
List.foldl (+) 0 (List.map square list)
Função de alta ordem
map : (a -> b) -> List a -> List b
map f l =
case l of
[] -> []
x :: xs -> f x :: map f xs
Lambda
sumOfSquares : List Int -> List Int
sumOfSquares list = List.foldl (+) 0 (List.map (x -> x*x) list)
Função de primeira classe
mkAdjectifier : String -> String -> String
mkAdjectifier adjective noun = adjective ++ " " ++ noun
coolifier : String -> String
coolifier = mkAdjectifier "cool"
-- coolifier "meetup" == "cool meetup"
Transforma a avaliação de uma função de vários argumentos na avaliação de uma
sequênciade funções de um argumento.
Facilita o uso de funções de vários argumentos e a aplicação parcial de funções.
Currying
f : ℤ × ℤ → ℤ ~ f : ℤ → ℤ → ℤ
Currying
addT : (Int, Int) -> Int
addT (a, b) = a + b
add : Int -> Int -> Int
add a b = a + b
-- add2 :: Int -> Int
add2 = add 2
-- five :: Int
five = add2 3 -- == 5
Mecanismo que combina funções simples para construir outras mais complexas.
Encoraja a fatoração de funções para melhor manutenção e reuso de código.
Composição de funções
( f ∘ g)(x) = f (g(x))
Operador de composição de funções
compose : (a -> b) -> (b -> c) -> (a -> c)
compose f g = a -> f (g a)
(point free) Composição de funções
squareList : List Int -> List Int
squareList = List.map (x -> x*x)
sumList : List Int -> List Int
sumList = List.foldl (+) 0
sumOfSquares : List Int -> List Int
sumOfSquares = sumList << squareList
Composição de funções
squareList : List Int -> List Int
squareList xs = List.map (x -> x*x) xs
sumList : List Int -> List Int
sumList xs = List.foldl (+) 0 xs
sumOfSquares : List Int -> List Int
sumOfSquares xs = (sumList << squareList) xs
Conjuntos de valores(não são classes).
Podem ser compostos.
Seus valores construídos e desestruturados(com pattern matching).
Garantem segurança.
Tipos
Construídos como operações algébricas sobre conjuntos.
Permitem a definição de tipos mais complexos.
Permitem a composição de tipos.
Tipos algébricos
Tipo soma e função com pattern matching
type PrimaryColor = Red | Blue | Yellow
nextColor : PrimaryColor -> PrimaryColor
nextColor color =
case color of
Red -> Blue
Blue -> Yellow
Yellow -> Red
Tipo produto e função com desestruturação
type Point = Point Int Int -- mkPoint : Int -> Int -> Point
addPoints : Point -> Point -> Point
addPoints (Point x1 y1) (Point x2 y2) = Point (x1 + x2) (y1 + y2)
(Elm) Records
type alias User = { name : String, email : String }
maria : User
maria = { name = "Maria", email = "maria@email.com" }
type User = User { name : String, email : String } type User = User String String~
Tipos recursivos
type List = Nil | Cons Int List
type NonEmptyList = Single Int | Cons Int List
type Tree = Tree String (List Tree)
type BTree = Empty | NodeLeft String BTree | NodeRight String BTree
Pattern matching em tipos recursivos
mapList : (Int -> Int) -> List -> List
mapList f l =
case l of
Nil -> Nil
Cons x xs -> Cons (f x) (mapList f xs)
mapList : (Int -> Int) -> List -> List
mapList f Nil = Nil
mapList f Cons x xs = Cons (f x) (mapList f xs)
mapTree : (String -> String) -> Tree -> Tree
mapTree f t =
case t of
Empty -> Empty
NodeLeft x xs -> NodeLeft (f x) (mapTree f xs)
NodeRight x xs -> NodeRight (f x) (mapTree f xs)
Tipos paramétricos
type Point a = Point a a
type Tuple a b = Tuple a b
p : Point Int
p = Point 1 3
p2 : Point Float
p2 = Point 1.2 3.4
user : Tuple Int String
user = Tuple 1 "Maria"
Tipos recursivos paramétricos
type List a = Nil | Cons a List -- mkCons : a -> List -> List
type NonEmptyList a = Single a | Cons a List
type Tree a = Tree a (List Tree)
type BTree a = Empty | NodeLeft a BTree | NodeRight a BTree
Tipos paramétricos e funções
type Maybe a = Nothing | Just a
type Either a b = Left a | Right b
head : List a -> Maybe a
head = …
parseMarkdown : String -> Either Error Markdown
parseMarkdown = …
Tipo soma e função parcial
type SecondaryColor = Orange | Green | Purple
addPrimaryColors : PrimaryColor -> PrimaryColor -> SecondaryColor
addPrimaryColors c1 c2 =
case (c1, c2) of
(Red, Blue) -> Purple
(Red, Yellow) -> Orange
(Blue, Red) -> Purple
(Blue, Yellow) -> Green
(Yellow, Red) -> Orange
(Yellow, Blue) -> Green
Tipo soma e função
type SecondaryColor = Orange | Green | Purple
addPrimaryColors : PrimaryColor -> PrimaryColor -> Either PrimaryColor SecondaryColor
addPrimaryColors c1 c2 =
case (c1, c2) of
(Red, Blue) -> Right Purple
(Red, Yellow) -> Right Orange
(Blue, Red) -> Right Purple
(Blue, Yellow) -> Right Green
(Yellow, Red) -> Right Orange
(Yellow, Blue) -> Right Green
_ -> Left c1
Tipo inseguro
type Permission = BlockUser | BanUser | RemovePosts
type UserType = Guest | User | Admin
type alias User =
{ name : Maybe String
, email : Maybe Email
, permissions : List Permission
, userType : UserType
}
Tipo seguro
type Permission = BlockUser | BanUser | RemovePosts
type User
= Guest
| User
{ name : String
, email : Email
}
| Admin
{ name : String
, email : Email
, permissions : List Permission
}
Tipo seguro++
type Permission = BlockUser | BanUser | RemovePosts
type User p
= Guest
| User
{ name : String
, email : Email
}
| Admin
{ name : String
, email : Email
, permissions : p
}
Ter de tratar todos os valores possíveis de um tipo ajuda a entender o domínio.
Quando uma função é parcial pode-se restringir sua entrada ou sua saída.
“Ah,vocênãosabiaqueessalistanãopodiaservazia?Culpasua!
ArrayOutOfBoundsException!!”
— Java Enterprise Edition
Totalidade
Funções totais
head : List a -> Maybe a
head = …
head : NonEmptyList a -> a
head = …~
Resolve problemas causados por estados mutáveis:
Condições de corrida, complexidade, imprevisibilidade…
Linguagens funcionais puras representam mutabilidade como efeito colateral.
Elm nem mesmo permitem mutabilidade.
Imutabilidade
Coleções como listas ou árvores são úteis para representar iterações sobre dados.
Mais do que isso elas permitem transformar múltiplos valores em outro tipo.
Coleções
Funções úteis do tipo List
head : List a -> Maybe a
tail : List a -> Maybe (List a)
range : Int -> Int -> List Int
(::) : a -> List a -> List a
append : List a -> List a -> List a
sort : List comparable -> List comparable
map : (a -> b) -> List a -> List b
map2 : (a -> b -> c) -> List a -> List b -> List c
foldr : (a -> b -> b) -> b -> List a -> b
foldl : (a -> b -> b) -> b -> List a -> b
filter : (a -> Bool) -> List a -> List a
Estruturas algébricas que implementam a operação map e seguem as leis:
map : (a -> b) -> f a -> f b
map id = id
map (f << g) = map f << map g
Functores
São contêineres que representam resultados de computações sobre outros tipos.
As computações representadas pelo functor são definidas pela forma do functor e
pelo comportamento da operação map.
Functores
Maybe
type Maybe a = Nothing | Just a
map : (a -> b) -> Maybe a -> Maybe b
map f maybe =
case maybe of
Nothing -> Nothing
Just a -> Just (f a)
Either
type Either a = Left a | Right a
map : (a -> b) -> Either a -> Either b
map f either =
case either of
Left a -> Left a
Right a -> Right (f a)
Tuple
map : (a -> b) -> (t, a) -> (t, b)
map f (tag, a) = (tag, f a)
List
map : (a -> b) -> List a -> List b
map f list =
case list of
[] -> []
x :: xs -> f x :: map f list
Maior previsibilidade.
Melhor testabilidade.
Facilidade de raciocínio.
Simplicidade.
Corretude.
Por quê programação funcional?*
Hands-on
TodoMVC++
Nesta primeira parte vamos apenas inserir notas no modelo e mostrá-las como
elementos Html na tela.
Vamos também inserir novas notas no modelo ao clicar em um botão.
Parte 1
Nesta segunda parte vamos tratar a edição de notas.
Quando o usuário clicar em uma nota deveremos poder editá-la. Ao pressionar
Enter, as modificações devem ser salvas no modelo.
Será necessário modificar o modelo para que seja possível identificar qual nota está
sendo editada no momento.
Parte 2
Nesta terceira parte veremos como Elm trata efeitos colaterais através de ports.
Faremos com que nossa aplicação salve o modelo quando ele for alterado no local
storage do browser.
Parte 3
Uma port em Elm é um valor ou função definido com a keyword port que deve
produzir um valor do tipo Cmd, um comando.
Precisaremos definir uma port que envia o modelo a ser salvo para o mundo externo.
Por conveniência já foi feito no arquivo index.html o tratamento dos comandos
recebidos pela port que iremos definir.
Parte 3
Nesta quarta parte veremos os benefícios dos tipos paramétricos.
Parametrizaremos o tipo Noteem relação a um tipo i que representa o campo de
identificação de uma nota.
Parte 4
Nesta quinta e última parte parametrizaremos o tipo Note em relação ao conteúdo.
Para que possamos usar tipos que não sejam String para representar o tipo de uma
nota, mas mantendo o tipo String como conteúdo das notas serializadas, devemos
parametrizar o tipo Note em relação ao conteúdo e tornar as funções que operam
sobre ele polimórficas sobre o conteúdo.
Parte 5
Recursos
An Introduction to Elm
http://guide.elm-lang.org/
Elm Examples
http://elm-lang.org/examples
Elm Search
https://klaftertief.github.io/elm-search/
Elm Packages
http://package.elm-lang.org/
https://github.com/arthur-xavier/workshop-intro-fp-elm

Programação funcional tipada: uma introdução

  • 1.
  • 2.
    meu nome éArthur Xavier Oi, Sou estudante de Ciência da Computação e apaixonado por Programação Funcional @arthurxavierx @arthur-xavier
  • 3.
    Maior previsibilidade. Melhor testabilidade. Facilidadede raciocínio. Simplicidade. Ajuda a evitar uma grande classe de bugs. Por quê programação funcional?
  • 4.
    Não é somenteprogramar com funções. É um paradigma de programação declarativo. Modela computações como o resultado da avaliação e composição de funções. Evita dados mutáveis e efeitos colaterais. Mas o que é programação funcional?
  • 5.
    function squareArrayImperative(arr) { letresult = []; for (let i = 0; i < arr.length; i++) { result.push(arr[i] ** 2); } return result; } Programação imperativa
  • 6.
    const squareArrayDeclarative =arr => arr.map(x => x ** 2); Programação declarativa
  • 7.
    squareList : ListInt -> List Int squareList xs = List.map (x -> x^2) xs (Elm) Programação declarativa
  • 8.
    Linguagem de programaçãopara a criação de interfaces web declarativas. Foco na usabilidade do desenvolvedor, performance e resiliência. Elm
  • 9.
    Fortemente tipada efuncional pura. Na prática, aplicações escritas em Elm não produzem exceções de runtime. Elm
  • 10.
    Uma função éuma expressão. Mapeia elementos de um domínio em elementos de um contradomínio. Funções
  • 11.
  • 12.
    Função f : ℤ→ ℕ = x ↦ |x|
  • 13.
    (Elm) Função f :Int -> Int f x = abs x
  • 14.
    Funções Seja um conjuntotal que: ε ∈ , ∀ x ∈ ℤ, ∀ α ∈ , x • α ∈ . Então squareL : → = α ↦ ε se α = ε x² • squareL(β) se α = x • β sumL : → ℤ = α ↦ 0 se α = ε x + sumL(β) se α = x • β
  • 15.
    (Elm) Funções squareList :List Int -> List Int squareList l = case l of [] -> [] x :: xs -> x^2 :: squareList xs sumList : List Int -> Int sumList l = case l of [] -> 0 x :: xs -> x + sumList xs
  • 16.
    Toda função épura. Funções impuras são chamadas de procedimentos, rotinasou subrotinas. Funções puras
  • 17.
    Uma função puraé uma função que sempre produz o mesmo resultado quando são passados os mesmos argumentos, e que não produz efeitos colaterais observáveis. Funções puras
  • 18.
    Efeitos colaterais “Uma funçãoou expressão produz efeitos colaterais se ela modifica algum estado fora de seu escopo ou realiza alguma interação observável com as funções que a chamaram ou com o mundo externo.” – Wikipedia
  • 19.
    Função impura function append(x){ this.array.push(x); }
  • 20.
  • 21.
    Função pura function appendToArray(array,x) { return [ ...array, x ]; }
  • 22.
    (Elm) Função pura appendToList: List Int -> Int -> List Int appendToList list x = list ++ [x]
  • 23.
    Função impura function sumOfSquares(array){ let result = 0; for (let x in array) { result += x*x; } console.log(result); };
  • 24.
    Função pura const square= x => x*x; const add = (a, b) => a + b; function sumOfSquares(array) { return array .map(square) .reduce(add, 0); } console.log(sumOfSquares([2, 3, 5]));
  • 25.
    (Elm) Função pura sumOfSquares: List Int -> Int sumOfSquares list = let square x = x*x in List.foldl (+) 0 (List.map square list) -- cadê o console.log??
  • 26.
    Como programação funcional pura podeser útil se não tem efeitos colaterais?
  • 27.
    Abestado, tem efeitos colateraissim, mas são. representados de forma diferente.
  • 28.
    Linguagens funcionais implementamfunções de primeira classe. Funções em linguagens funcionais são valores. Funções podem ser passadas como argumentos para outras funções. Funções podem ser valores de retorno de outras funções. Funções de primeira classe
  • 29.
    São funções querecebem outras funções como argumento. map reduce / fold filter Funções de alta ordem
  • 30.
    Funções de altaordem sumOfSquares : List Int -> List Int sumOfSquares list = let square x = x*x in List.foldl (+) 0 (List.map square list)
  • 31.
    Função de altaordem map : (a -> b) -> List a -> List b map f l = case l of [] -> [] x :: xs -> f x :: map f xs
  • 32.
    Lambda sumOfSquares : ListInt -> List Int sumOfSquares list = List.foldl (+) 0 (List.map (x -> x*x) list)
  • 33.
    Função de primeiraclasse mkAdjectifier : String -> String -> String mkAdjectifier adjective noun = adjective ++ " " ++ noun coolifier : String -> String coolifier = mkAdjectifier "cool" -- coolifier "meetup" == "cool meetup"
  • 34.
    Transforma a avaliaçãode uma função de vários argumentos na avaliação de uma sequênciade funções de um argumento. Facilita o uso de funções de vários argumentos e a aplicação parcial de funções. Currying f : ℤ × ℤ → ℤ ~ f : ℤ → ℤ → ℤ
  • 35.
    Currying addT : (Int,Int) -> Int addT (a, b) = a + b add : Int -> Int -> Int add a b = a + b -- add2 :: Int -> Int add2 = add 2 -- five :: Int five = add2 3 -- == 5
  • 36.
    Mecanismo que combinafunções simples para construir outras mais complexas. Encoraja a fatoração de funções para melhor manutenção e reuso de código. Composição de funções ( f ∘ g)(x) = f (g(x))
  • 37.
    Operador de composiçãode funções compose : (a -> b) -> (b -> c) -> (a -> c) compose f g = a -> f (g a)
  • 38.
    (point free) Composiçãode funções squareList : List Int -> List Int squareList = List.map (x -> x*x) sumList : List Int -> List Int sumList = List.foldl (+) 0 sumOfSquares : List Int -> List Int sumOfSquares = sumList << squareList
  • 39.
    Composição de funções squareList: List Int -> List Int squareList xs = List.map (x -> x*x) xs sumList : List Int -> List Int sumList xs = List.foldl (+) 0 xs sumOfSquares : List Int -> List Int sumOfSquares xs = (sumList << squareList) xs
  • 40.
    Conjuntos de valores(nãosão classes). Podem ser compostos. Seus valores construídos e desestruturados(com pattern matching). Garantem segurança. Tipos
  • 41.
    Construídos como operaçõesalgébricas sobre conjuntos. Permitem a definição de tipos mais complexos. Permitem a composição de tipos. Tipos algébricos
  • 42.
    Tipo soma efunção com pattern matching type PrimaryColor = Red | Blue | Yellow nextColor : PrimaryColor -> PrimaryColor nextColor color = case color of Red -> Blue Blue -> Yellow Yellow -> Red
  • 43.
    Tipo produto efunção com desestruturação type Point = Point Int Int -- mkPoint : Int -> Int -> Point addPoints : Point -> Point -> Point addPoints (Point x1 y1) (Point x2 y2) = Point (x1 + x2) (y1 + y2)
  • 44.
    (Elm) Records type aliasUser = { name : String, email : String } maria : User maria = { name = "Maria", email = "maria@email.com" } type User = User { name : String, email : String } type User = User String String~
  • 45.
    Tipos recursivos type List= Nil | Cons Int List type NonEmptyList = Single Int | Cons Int List type Tree = Tree String (List Tree) type BTree = Empty | NodeLeft String BTree | NodeRight String BTree
  • 46.
    Pattern matching emtipos recursivos mapList : (Int -> Int) -> List -> List mapList f l = case l of Nil -> Nil Cons x xs -> Cons (f x) (mapList f xs) mapList : (Int -> Int) -> List -> List mapList f Nil = Nil mapList f Cons x xs = Cons (f x) (mapList f xs) mapTree : (String -> String) -> Tree -> Tree mapTree f t = case t of Empty -> Empty NodeLeft x xs -> NodeLeft (f x) (mapTree f xs) NodeRight x xs -> NodeRight (f x) (mapTree f xs)
  • 47.
    Tipos paramétricos type Pointa = Point a a type Tuple a b = Tuple a b p : Point Int p = Point 1 3 p2 : Point Float p2 = Point 1.2 3.4 user : Tuple Int String user = Tuple 1 "Maria"
  • 48.
    Tipos recursivos paramétricos typeList a = Nil | Cons a List -- mkCons : a -> List -> List type NonEmptyList a = Single a | Cons a List type Tree a = Tree a (List Tree) type BTree a = Empty | NodeLeft a BTree | NodeRight a BTree
  • 49.
    Tipos paramétricos efunções type Maybe a = Nothing | Just a type Either a b = Left a | Right b head : List a -> Maybe a head = … parseMarkdown : String -> Either Error Markdown parseMarkdown = …
  • 50.
    Tipo soma efunção parcial type SecondaryColor = Orange | Green | Purple addPrimaryColors : PrimaryColor -> PrimaryColor -> SecondaryColor addPrimaryColors c1 c2 = case (c1, c2) of (Red, Blue) -> Purple (Red, Yellow) -> Orange (Blue, Red) -> Purple (Blue, Yellow) -> Green (Yellow, Red) -> Orange (Yellow, Blue) -> Green
  • 51.
    Tipo soma efunção type SecondaryColor = Orange | Green | Purple addPrimaryColors : PrimaryColor -> PrimaryColor -> Either PrimaryColor SecondaryColor addPrimaryColors c1 c2 = case (c1, c2) of (Red, Blue) -> Right Purple (Red, Yellow) -> Right Orange (Blue, Red) -> Right Purple (Blue, Yellow) -> Right Green (Yellow, Red) -> Right Orange (Yellow, Blue) -> Right Green _ -> Left c1
  • 52.
    Tipo inseguro type Permission= BlockUser | BanUser | RemovePosts type UserType = Guest | User | Admin type alias User = { name : Maybe String , email : Maybe Email , permissions : List Permission , userType : UserType }
  • 53.
    Tipo seguro type Permission= BlockUser | BanUser | RemovePosts type User = Guest | User { name : String , email : Email } | Admin { name : String , email : Email , permissions : List Permission }
  • 54.
    Tipo seguro++ type Permission= BlockUser | BanUser | RemovePosts type User p = Guest | User { name : String , email : Email } | Admin { name : String , email : Email , permissions : p }
  • 55.
    Ter de tratartodos os valores possíveis de um tipo ajuda a entender o domínio. Quando uma função é parcial pode-se restringir sua entrada ou sua saída. “Ah,vocênãosabiaqueessalistanãopodiaservazia?Culpasua! ArrayOutOfBoundsException!!” — Java Enterprise Edition Totalidade
  • 56.
    Funções totais head :List a -> Maybe a head = … head : NonEmptyList a -> a head = …~
  • 57.
    Resolve problemas causadospor estados mutáveis: Condições de corrida, complexidade, imprevisibilidade… Linguagens funcionais puras representam mutabilidade como efeito colateral. Elm nem mesmo permitem mutabilidade. Imutabilidade
  • 58.
    Coleções como listasou árvores são úteis para representar iterações sobre dados. Mais do que isso elas permitem transformar múltiplos valores em outro tipo. Coleções
  • 59.
    Funções úteis dotipo List head : List a -> Maybe a tail : List a -> Maybe (List a) range : Int -> Int -> List Int (::) : a -> List a -> List a append : List a -> List a -> List a sort : List comparable -> List comparable map : (a -> b) -> List a -> List b map2 : (a -> b -> c) -> List a -> List b -> List c foldr : (a -> b -> b) -> b -> List a -> b foldl : (a -> b -> b) -> b -> List a -> b filter : (a -> Bool) -> List a -> List a
  • 60.
    Estruturas algébricas queimplementam a operação map e seguem as leis: map : (a -> b) -> f a -> f b map id = id map (f << g) = map f << map g Functores
  • 61.
    São contêineres querepresentam resultados de computações sobre outros tipos. As computações representadas pelo functor são definidas pela forma do functor e pelo comportamento da operação map. Functores
  • 62.
    Maybe type Maybe a= Nothing | Just a map : (a -> b) -> Maybe a -> Maybe b map f maybe = case maybe of Nothing -> Nothing Just a -> Just (f a)
  • 63.
    Either type Either a= Left a | Right a map : (a -> b) -> Either a -> Either b map f either = case either of Left a -> Left a Right a -> Right (f a)
  • 64.
    Tuple map : (a-> b) -> (t, a) -> (t, b) map f (tag, a) = (tag, f a)
  • 65.
    List map : (a-> b) -> List a -> List b map f list = case list of [] -> [] x :: xs -> f x :: map f list
  • 66.
    Maior previsibilidade. Melhor testabilidade. Facilidadede raciocínio. Simplicidade. Corretude. Por quê programação funcional?*
  • 67.
  • 69.
    Nesta primeira partevamos apenas inserir notas no modelo e mostrá-las como elementos Html na tela. Vamos também inserir novas notas no modelo ao clicar em um botão. Parte 1
  • 70.
    Nesta segunda partevamos tratar a edição de notas. Quando o usuário clicar em uma nota deveremos poder editá-la. Ao pressionar Enter, as modificações devem ser salvas no modelo. Será necessário modificar o modelo para que seja possível identificar qual nota está sendo editada no momento. Parte 2
  • 71.
    Nesta terceira parteveremos como Elm trata efeitos colaterais através de ports. Faremos com que nossa aplicação salve o modelo quando ele for alterado no local storage do browser. Parte 3
  • 72.
    Uma port emElm é um valor ou função definido com a keyword port que deve produzir um valor do tipo Cmd, um comando. Precisaremos definir uma port que envia o modelo a ser salvo para o mundo externo. Por conveniência já foi feito no arquivo index.html o tratamento dos comandos recebidos pela port que iremos definir. Parte 3
  • 73.
    Nesta quarta parteveremos os benefícios dos tipos paramétricos. Parametrizaremos o tipo Noteem relação a um tipo i que representa o campo de identificação de uma nota. Parte 4
  • 74.
    Nesta quinta eúltima parte parametrizaremos o tipo Note em relação ao conteúdo. Para que possamos usar tipos que não sejam String para representar o tipo de uma nota, mas mantendo o tipo String como conteúdo das notas serializadas, devemos parametrizar o tipo Note em relação ao conteúdo e tornar as funções que operam sobre ele polimórficas sobre o conteúdo. Parte 5
  • 75.
    Recursos An Introduction toElm http://guide.elm-lang.org/ Elm Examples http://elm-lang.org/examples Elm Search https://klaftertief.github.io/elm-search/ Elm Packages http://package.elm-lang.org/ https://github.com/arthur-xavier/workshop-intro-fp-elm