Como você cria programas em Haskell ou outras linguagens de programação funcional?


52

Tenho alguma experiência em linguagens de programação orientada a objetos como c # ou ruby. Eu sei como projetar um programa no estilo orientado a objetos, como criar classes e objetos e como definir relações entre eles. Eu também conheço alguns padrões de design.

Como as pessoas escrevem programas funcionais? Como eles começam? Existem padrões de design para linguagens funcionais? Metodologias como programação extrema ou desenvolvimento ágil são aplicáveis ​​a linguagens funcionais?


Respostas:


24

Escrevo minha resposta principalmente com Haskell em mente, embora muitos conceitos se apliquem igualmente bem a outras linguagens funcionais como Erlang, Lisp (s) e ML. Alguns até se aplicam (até certo ponto) a Ruby, Python, Perl e Javascript.

Como as pessoas escrevem programas funcionais? Como eles começam?

Escrevendo funções. Quando você está fazendo programação funcional, está escrevendo mainou escrevendo uma função auxiliar. Às vezes, seu principal objetivo pode ser escrever um tipo de dados com várias funções relevantes que operam nele.

A programação funcional é muito adequada para abordagens de cima para baixo e de baixo para cima. Haskell incentiva fortemente a escrever seus programas em linguagem de alto nível e, em seguida, simplesmente definir os detalhes do seu design de alto nível. Veja minimum, por exemplo:

minimum    :: (Ord a) => [a] -> a
minimum xs =  foldl1 min xs

A função para encontrar o menor elemento em uma lista é escrita simplesmente como uma travessia sobre a lista, usando a função min para comparar cada elemento com o "acumulador" ou o valor mínimo atual.

Existem padrões de design para linguagens funcionais?

Há duas coisas que podem ser equiparadas a "padrões de design", imho, funções de ordem superior e mônadas . Vamos falar sobre o primeiro. Funções de ordem superior são funções que assumem outras funções como entrada ou produzem funções como saída. Qualquer linguagem funcional geralmente faz uso pesado de map, filterefold(fold é também chamado de "reduzir"): três funções básicas de ordem superior que aplicam uma função a uma lista de maneiras diferentes. Estes substituem o boilerplate por loops de uma maneira bonita. Passar funções como parâmetros é um benefício extremamente poderoso para a programação; muitos "padrões de design" podem ser realizados de maneira mais simples, usando funções de ordem superior, criando suas próprias e aproveitando a poderosa biblioteca padrão, cheia de funções úteis.

Mônadas são o tópico "mais assustador". Mas eles não são realmente tão assustadores. Minha maneira favorita de pensar nas mônadas é pensar nelas como envolvendo uma função em uma bolha e dando superpoderes a essa função (que só funcionam dentro da bolha). Eu poderia elaborar, mas o mundo realmente não precisa de mais uma analogia com mônada. Então, vou passar para exemplos rápidos. Suponha que eu queira usar um "padrão de design" não determinístico. Eu quero executar o mesmo cálculo para várias entradas diferentes ao mesmo tempo. Não quero escolher apenas uma entrada, quero escolher todas elas. Essa seria a mônada da lista:

allPlus2 :: [Int] -> [Int]
allPlus2 xs = do x <- xs
                 return (x + 2)

Agora, a maneira idiomática de fazer isso é realmente map, mas, para fins de ilustração, você pode ver como a mônada da lista me permitiu escrever uma função que parece funcionar em um valor, mas dotada de superpotência para trabalhar em todos os elementos uma lista? Outras superpotências incluem falha, estado, interação com o "mundo exterior" e execução paralela. Essas superpotências são muito potentes, e a maioria das linguagens de programação permite que funções com superpotências se espalhem por toda parte. A maioria das pessoas diz que Haskell não permite essas superpotências, mas, na verdade, Haskell as contém apenas em mônadas, para que seus efeitos possam ser limitados e observados.

As funções e mônadas de ordem superior do Grokking são o equivalente Haskell aos padrões de design do grokking. Depois de aprender esses conceitos de Haskell, você começa a pensar que "padrões de design" são soluções alternativas mais baratas para simular o poder de Haskell.

Metodologias como programação extrema ou desenvolvimento ágil são aplicáveis ​​a linguagens funcionais?

Não vejo nada que vincule essas estratégias de gerenciamento a nenhum paradigma de programação. Como o phynfo afirmou, a programação funcional praticamente obriga a decompor funções, dividindo um grande problema em subproblemas, de modo que os mini-marcos devem ser um pedaço de bolo. Existem ferramentas como o QuickCheck e o Zeno para testar ou até provar propriedades sobre as funções que você escreve.


"Eu poderia elaborar, mas o mundo realmente não precisa de mais uma analogia de mônada." - Sempre precisamos de mais analogias para mônadas e a sua é uma das melhores que já vi.
Adam Gent

11
Ótima resposta, mas acho que sua discussão sobre padrões de design é um pouco enganadora. Embora você não precise de padrões de design no estilo OO / GOF em Haskell - na verdade, seria ridículo experimentá-los - os próprios padrões são simplesmente maneiras pelas quais uma comunidade comunica soluções para os tipos de problemas que surgem repetidamente. A comunidade Haskell ainda é muito jovem, então ainda não há muitos padrões para falar, mas se você me pedisse exemplos de padrões Haskell, eu mencionaria coisas como GADTs ou Arrowized FRP.
Rtperson
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.