Os falsos medos da programação funcional

Ahhhh já consigo te ouvir gritando e suspirando: “Mais post sobre Programação Funcional, qual é o problema disso? Por que eu deveria mudar minha maneira de pensar agora?”
Tente inverter essas questões e pergunte a si mesmo: estamos falando de programação aqui, talvez porque isso vá te ajudar?
Talvez isso possa tornar seu código mais fácil de ler e mais sustentável?
Você está relaxado, agora? Tudo bem, vamos abordar alguns “medos” (mesmo que não devessem ser) sobre Programação Funcional (PF), certo?
Como o Javascript está cada vez mais se transformando em uma linguagem Assembly para navegadores, existem várias bibliotecas/frameworks que fazem uso de princípios FP, além do código escrito nessas linguagens ser compilado em JS para ser usado em todos os navegadores.

Nós vamos usar roteiro puro em nossos exemplos, pois é mais conciso e fácil de ler do que JS puro.

Introdução básica aos termos e paradigma FP (Usando Purescript VS Pure JS)

Logo PureScriptPrimeiro, gostaria de familiarizá-lo com alguns conceitos básicos sobre FP. Programação Funcional, como o nome sugere,
é baseado no Paradigma Funcional (Você não diz?) onde tudo é um função, aquelas funções que adoramos da matemática (palavra-gatilho), lembra? De A a B, ou de Integer a Integer, você nomeia.
Exemplo:

addMeFive::Int -> Int addMeFive x = x + 5

vs

function addMeFive(x) {
return x + 5
}

Se você se lembra corretamente, as funções, por definição, ao receber a mesma entrada repetidamente,
retorna o mesmo resultado toda vez (Alimento funções).

addMeFive 5 = 10 -- e não há como obter qualquer outra resposta desta chamada.

Esses pequeninos têm propriedades legais como composição que é a base para criar programas mais complexos em FP.

A composição não é a única maneira de unir funções

Composição das funções f e g.

g::a -> b f::b -> c

Se existe uma função de a para b e outra de b para c então também existe uma função de a para c e pode ser definida pela composição das duas últimas funções.

-- f <<< g lê - f depois de g f <<< g :: a -> c

As variáveis ​​são imutável, por padrão ou se não, deve ser claramente indicado.

a=5 a=8 -- não é permitido.

Como você provavelmente pode ver, se as variáveis ​​são imutáveis, as condições de corrida não são um problema, pois é uma consequência
de estado mutável. Assim, em FP, a simultaneidade e a operação paralela são mais fáceis de lidar.

Tipos são extremamente importantes na Programação Funcional.

Nem todas as linguagens de programação funcionais são fortemente tipadas, os tipos nos incentivam, porém a pensar primeiro nos relacionamentos em nosso Software ao invés de correr e codificar sem pensar.
Um tipo especial de tipos são os tipos polimórficos. Polimorfismo nos permite usar a mesma função, mas com tipos de entrada diferentes, esses tipos construíram a base para os tipos genéricos conhecidos em linguagens OOP como Java, C# e assim por diante.

length::[a] -> Int -- retorna o comprimento de uma lista do tipo a

Depois do básico, um dos aspectos importantes da programação funcional é Funções de ordem superior (HOF).
É onde as funções se tornam interessantes, sabemos que funções recebem uma entrada e retornam uma saída, até agora eram apenas Integers, Strings, um tipo aleatório a, etc.
E se dermos uma função como argumento? É isso, você acabou de atualizar sua função.
Exemplo:

mapa:: (a->b) -> [a] -> [b]

map é uma função que retorna uma lista onde a função dada como argumento foi aplicada a cada elemento da lista dada.

map é uma função bastante importante, portanto, mantenha-a em mente.

Abstração: OOP vs. FP

As mônadas
Agora, temos algum entendimento (muito) básico sobre FP, vamos falar sobre abstração por um segundo.
Definição de Abstração (que melhor se adequa à Ciência da Computação): “A qualidade de lidar com ideias em vez de eventos.”
Não queremos lidar com eventos concretos ou detalhados porque há muitos fatores que bloquearão nossa maneira de pensar, então abstraímos, perdendo alguns detalhes, mas mantendo o foco do problema (as ideias da definição) .
Espere o que?
Para ser mais conciso, escolhemos a dedo as partes mais importantes do nosso problema e os detalhes restantes são esquecidos, facilitando não apenas a estrutura de nossos tipos/objetos, mas também nossos programas gerais.
Em OOP, a abstração é alcançada simplesmente representando “Coisas”, embora, não em toda a sua complexidade,
apenas as propriedades importantes. Então você pode fazer “Coisas” com a entidade abstrata, e é praticamente isso.
Aliás, a “coisa” se chama objeto e "Coisas" é Forma.
Em FP, tentamos maximizar a abstração, cortamos nossos problemas em funções simples que depois serão compostas para criar funções mais complexas resultando em um programa que faça o que queríamos. Não se concentra apenas na representação das “Coisas”, mas nas relações entre elas, que é o nosso foco. Criamos nossos tipos básicos e então, se precisarmos ter tipos mais complexos, podemos combiná-los com vários operadores, por exemplo, A + B (A ou B ou o Tipo União), A x B (A vezes B, Ou o par tipo) e alguns outros.

Padrões FP 101

Lá estamos nós, o verdadeiro ponto de toda essa divagação, Padrões FP, não deve ser confundido com os Padrões de Design da OOP, os padrões FP são sobre o reconhecimento da repetição, você sabe, o real significado dos padrões (você precisa tentar mais OOP).
Vamos então falar sobre Currying, Functors, Catamorfismo e Anamorfismo (ou respectivamente, Escovando, Mapa, Dobre e Desdobrar). Por uma questão de simplicidade, usarei Listas para explicar os três últimos:

Escovando

Curry (não o prato) é o que fazemos quando transformamos funções com mais de um argumento em funções que recebem um argumento e depois retornam uma função responsável por receber os argumentos restantes. Isso facilita a possibilidade de composição/encadeamento.

curry :: ((a,b)->c) -> a -> b -> c

Mapa também conhecido como Functor

Mapa aka functor é a aplicação de uma função em uma estrutura complexa. Para listas, fica assim:

mapa:: (a->b) -> [a] -> [b]

por exemplo, quando você deseja dobrar os elementos de uma lista, em vez do bom e velho loop for, por que não:

map((elem)=> elem*2)[1,2,3]=map(*2)[1,2,3]=[2,4,6]

Reduzir aka Catamorfismo aka Fold

Catamorfismo do grego: κατά “para baixo” e μορφή “forma, forma” ou também conhecido Dobre é a capacidade de reduzir uma estrutura em outra estrutura, também conhecida como Conquistar da Dividir e conquistar.

fold::forall abc . (a->b->b) -> b -> [a] -> b

por exemplo Quer calcular a soma de uma lista de inteiros? Sem problemas

fold ((elem,acc)=> acc + elem) 0 [1,2,3] = 6

Para ser mais explícito, fold é a função recursiva com lista de tipos de entrada e saída do tipo que você quiser. Se desconstruirmos nosso exemplo na função correspondente:

sum::[int] -> int sum[] = 0 -- segundo argumento do nosso fold sum (x:xs) = x + sum xs -- mesmo comportamento das funções recebidas como argumento no nosso exemplo de fold

Gerar aka Anamorphism aka Unfold

Anamorfismo do grego ἀνά "para cima" e μορφή "forma, forma" ou também conhecido como Desdobrar é a capacidade de gerar uma estrutura de outra estrutura, o Dividir do Dividir e Conquistar.

desdobrar :: (b->Talvez (Tupla ab)) -> b -> [a]

Isso parece mais complicado, no entanto, a função (b-&gt;(Tuple a b)) é responsável por gerar os elementos da lista de saída.
por exemplo, gerar lista de 10 a 1

desdobra(semente -> se semente == 0 então Nada mais Apenas(semente,semente-1)) 10 = [10,9,8,7,6,5,4,3,2,1] generateList::Int - > [Int] generateList seed = if seed == 0 then [] else seed:(generateList seed-1)

Uma mudança para FP

Depois de analisar alguns dos padrões de PF, a pergunta que você fez em sua cabeça no início do artigo (lembre-se). Por que todas as linguagens, incluindo JavaScript, estão se movendo em direção à programação funcional? Acho que se você ler até este ponto entenderá o fato de que funções são abstrações poderosas. São fáceis de ler e codificar e, como passamos a codificar funções minúsculas, isso nos permite colá-las como Legos para construir programas maiores.
Escrito por João Ribeiro
PS: Você pode dar uma olhada na minha palestra e na conversa do BloodyOwl (em francês) sobre PuroScript e Razão lá:
http://blog.js-republic.com/meetup-js-star-reason-purescript-programmation-fp/