Estou interessado em aprender melhor a programação funcional. Para fazer isso, parece óbvio que devo me forçar a usar a linguagem de programação funcional mais pura possível. Por isso, estou aqui pedindo, mais ou menos, um pedido de linguagens de programação funcionais de acordo com sua pureza.
Parece-me que seria mais prático aprender Lisp ou Clojure (ou Scheme, ou Scala etc.), mas pelo que ouvi recentemente, seria muito difícil vencer Haskell ao ensinar princípios de programação funcional a alguém. Ainda não tenho certeza disso, então estou perguntando: qual é a linguagem de programação funcional mais pura? Um pedido seria ótimo se vários estivessem competindo pelo magnífico título da mais pura linguagem de programação funcional.
Respostas:
Não há escala para avaliar o grau de pureza das linguagens funcionais. Se a linguagem permite efeitos colaterais, é impura; caso contrário, é pura. Por essa definição, Haskell, Mercury, Clean etc são linguagens funcionais puras; enquanto Scala, Clojure, F #, OCaml etc são impuros.
EDIT: Talvez eu devesse ter formulado isso como "se a linguagem não permitir efeitos colaterais sem informar o sistema de tipos , é puro. Caso contrário, é impuro".
fonte
IO
mônada). É que o código causador de efeitos colaterais está claramente marcado como tal. Eu não acho que seja útil falar em linguagens puras / impuras (Haskell permite programar imperativamente! Suspiro!), Mas ainda pode ser útil falar em pedaços de código (função, módulo, programa, o que for) como puros /impuro.IO
mônada é pura. É a biblioteca de tempo de execução que não é, não é seu código, pois suamain
função é basicamente um enorme transformador de estado. (Algo comomain :: World -> World
nos bastidores)program = "some C code"
e, em seguida, o ambiente de tempo de execução lida com o código C. :-)Como aprender é o seu objetivo, e não escrever programas por si só, você não pode obter nada mais puro do que o Lambda Calculus .
O Cálculo Lambda existia antes dos computadores serem inventados. Foram necessários vários lógicos habilidosos trabalhando para descobrir como fazer a subtração (por um tempo foi teorizado que apenas a adição e a multiplicação eram possíveis).
Aprender como booleanos e números e
if
pode ser inventado a partir de aparentemente nada não colocará mais gás em seu tanque, mas fará com que seu tanque seja muito maior.fonte
-1
.As linguagens impuras realmente não diferem em princípio das linguagens imperativas mais familiares, especialmente agora que muitos truques funcionais foram copiados. O que é diferente é o estilo - como você resolve problemas.
Se você considera Haskell puro, ou conta a mônada de IO como impureza, o estilo Haskell é uma forma extrema desse estilo e vale a pena aprender.
A mônada Haskell IO é derivada da teoria matemática das mônadas (é claro). No entanto, para programadores imperativos, acho que uma maneira inversa de chegar às mônadas faz mais sentido.
Fase um - uma linguagem funcional pura pode facilmente retornar um grande valor de string como resultado. Essa grande cadeia pode ser o código-fonte de um programa imperativo, derivado de maneira funcional pura de alguns parâmetros de especificação de requisitos. Você pode criar um compilador de "nível superior" que executa seu gerador de código e, em seguida, alimenta automaticamente esse código gerado no compilador de linguagem imperativa.
Fase dois - em vez de gerar código fonte textual, você gera uma árvore de sintaxe abstrata fortemente tipada. Seu compilador de linguagem imperativa é absorvido pelo compilador "de nível superior" e aceita o AST diretamente como código-fonte. Isso é muito mais próximo do que Haskell faz.
Isso ainda é estranho, no entanto. Por exemplo, você tem dois tipos distintos de funções - aquelas avaliadas durante a fase de geração de código e as executadas quando o programa gerado é executado. É um pouco como a distinção entre funções e modelos em C ++.
Portanto, para a fase 3, torne os dois iguais - a mesma função com a mesma sintaxe pode ser parcialmente avaliada durante a "geração de código", ou totalmente avaliada, ou não avaliada. Além disso, descarte todos os nós AST da construção em loop em favor da recursão. De fato, descarte a ideia de nós AST como um tipo especial de dados - não tenha nós AST de "valor literal", apenas valores etc.
Isso é basicamente o que a mônada de E / S faz - o operador de ligação é uma maneira de compor "ações" para formar programas. Não é nada de especial - apenas uma função. Muitas expressões e funções podem ser avaliadas durante a "geração de código", mas aquelas que dependem dos efeitos colaterais de E / S devem ter a avaliação atrasada até o tempo de execução - não por nenhuma regra especial, mas como uma consequência natural das dependências de dados em expressões.
Mônadas em geral são apenas generalizações - elas têm a mesma interface, mas implementam as operações abstratas de maneira diferente; portanto, em vez de avaliar uma descrição do código imperativo, elas avaliam para outra coisa. Ter a mesma interface significa que há algumas coisas que você pode fazer com as mônadas sem se importar com a mônada, o que acaba sendo útil.
Essa descrição sem dúvida fará explodir cabeças de puristas, mas para mim explica algumas das reais razões pelas quais Haskell é interessante. Ele obscurece a fronteira entre programação e metaprogramação e usa as ferramentas de programação funcional para reinventar a programação imperativa sem precisar de sintaxe especial.
Uma crítica que tenho aos modelos C ++ é que eles são uma espécie de sublanguagem funcional pura e quebrada em uma linguagem imperativa - para avaliar a mesma função básica em tempo de compilação, em vez de em tempo de execução, é necessário reimplementá-la usando um estilo completamente diferente de codificação. Em Haskell, embora a impureza deva ser rotulada como tal em seu tipo, a mesma função exata pode ser avaliada no sentido de metaprogramação e no sentido de não metaprogramação em tempo de execução no mesmo programa - não há linha dura entre programação e metaprogramação.
Dito isto, existem algumas coisas de metaprogramação que Haskell padrão não pode fazer, basicamente porque tipos (e talvez algumas outras coisas) não são valores de primeira classe. Existem variantes de idioma que tentam resolver isso, no entanto.
Muitas coisas que eu disse sobre Haskell podem ser aplicadas em linguagens funcionais impuras - e às vezes até em linguagens imperativas. Haskell é diferente porque você não tem escolha a não ser adotar essa abordagem - basicamente obriga você a aprender esse estilo de trabalho. Você pode "escrever C em ML", mas não pode "escrever C em Haskell" - pelo menos não sem aprender o que está acontecendo sob o capô.
fonte
Pessoalmente, categorizo os idiomas em três níveis de pureza funcional:
Linguagens funcionais puras - ou seja, aquelas que tratam todo o programa como uma função pura e manipulam a mutabilidade apenas por meio da interação com o tempo de execução - Haskell é provavelmente o exemplo canônico
Linguagens funcionais impuras - ou seja, aquelas que enfatizam um estilo funcional, mas permitem efeitos colaterais. O Clojure está claramente nessa categoria (permite a mutação de maneira controlada como parte de sua estrutura STM), também OCaml ou F #
Linguagens multiparadigmas - essas não são linguagens funcionais em primeiro lugar, mas podem suportar um estilo funcional pelo uso de funções de primeira classe etc. Scala é um bom exemplo aqui, eu também colocaria o Common Lisp nessa categoria e você pode até incluir idiomas como JavaScript .
Na sua situação, sugiro aprender Haskell primeiro, depois Clojure. Foi isso que fiz e funcionou muito bem para mim! Haskell é bonito e ensina os princípios funcionais mais puros, Clojure é muito mais pragmático e ajuda a fazer muito enquanto ainda é muito funcional no coração.
Na verdade, não conto a terceira categoria como linguagens funcionais (embora depois de aprender Haskell e Clojure, muitas vezes eu me aproveitei das técnicas funcionais ao usá-las!)
fonte
Se uma linguagem funcional pura é tal, que possui apenas funções puras (rotinas que não têm efeitos colaterais), então é um pouco inútil, porque ela não pode ler entrada nem gravar saída;)
Porque isso é realmente para aprender, acho que o isolamento não é necessariamente o caminho a percorrer. A programação funcional é um paradigma. É importante entender quais paradigmas são adequados para quais problemas e, mais importante, como eles podem ser melhor combinados.
Fora isso, se você está procurando "pureza", pode querer dar uma olhada no Pure . Note, no entanto, a extrema facilidade de chamar as rotinas C torna funcionalmente impuro (mas também muito poderoso).
fonte
Não é uma resposta totalmente séria, mas Unlambda tem que ser um candidato. Você não pode ser mais "puro funcional" do que os combinadores de SKI.
fonte
Erlang, Haskell, Scheme, Scala, Clojure e F #
Esta questão seria provavelmente melhor que você ajudá-lo em sua busca como bem .
fonte
set!
(entre outras coisas) ...