Por que a sintaxe da linguagem funcional não está mais próxima da linguagem humana?

14

Estou interessado em programação funcional e decidi entrar em confronto com Haskell. Minha cabeça dói ... mas acabo entendendo ... Tenho uma curiosidade, por que a sintaxe é tão enigmática (na falta de outra palavra)?

Existe uma razão pela qual não é mais expressivo , mais próximo da linguagem humana?

Entendo que o FP é bom em modelar conceitos matemáticos e emprestou alguns de seus meios concisos de expressão, mas ainda não é matemática ... é uma linguagem.

JohnDoDo
fonte
4
@ catraca aberração: :) Então, há um projetado por um cara que odeia notação polonês?
JohnDoDo
10
@ratchetfreak De que maneira a sintaxe Haskell se assemelha à notação polonesa? Os operadores Haskell são infix, assim como os operadores da maioria dos outros idiomas (e as chamadas de função são prefixo - também como as chamadas de função da maioria dos outros idiomas).
sepp2k
9
Essa é uma grande suposição / salto que você está fazendo, que "mais próximo da linguagem humana" equivale a "mais expressivo".
Matt Bola
7
Já ouviu falar de Cobol e Fortran?
5--12
7
Pela mesma razão que os matemáticos substituíram longas frases em latim por expressões algébricas. Com um pouco de prática, uma notação mais compacta é muito mais produtiva.
Kevin cline #

Respostas:

14

Linguagens funcionais como Haskell e seu antecedente Miranda surgiram do conceito matemático do cálculo lambda . Na página da Wikipedia:

O cálculo lambda (também escrito como λ-calculus ou chamado "cálculo lambda") é um sistema formal em lógica matemática para expressar a computação por meio de ligação e substituição de variáveis.

...

O cálculo lambda tem desempenhado um papel importante no desenvolvimento da teoria das linguagens de programação. As contrapartes mais proeminentes do cálculo lambda na ciência da computação são as linguagens de programação funcional, que implementam essencialmente o cálculo (aumentado com algumas constantes e tipos de dados). Além das linguagens de programação, o cálculo lambda também tem muitas aplicações na teoria de provas. Um exemplo importante disso é a correspondência de Curry-Howard, que fornece uma correspondência entre diferentes sistemas de cálculo lambda digitado e sistemas de lógica formal.

Devido a essa história, as sintaxes dessas linguagens funcionais (e elementos funcionais de linguagens mais imperativas) são fortemente influenciadas pela notação matemática usada pelo cálculo lambda.

A precisão com a qual as notações matemáticas e as linguagens de computador podem descrever os requisitos e a precisão com a qual os computadores exigem que suas instruções sejam escritas estão bem correlacionadas. A imprecisão da linguagem natural, no entanto, cria uma enorme barreira ao seu uso na programação de computadores. Mesmo os ambientes de programação de linguagem natural (sem dúvida) mais bem-sucedidos , como o Wolfram Alpha, precisam de uma experiência significativa no domínio para serem usados ​​com eficiência.

Mark Booth
fonte
29

A sintaxe de Haskell está próxima da linguagem humana. Ele é projetado especificamente para se parecer com notação matemática, que é uma linguagem projetada por seres humanos (portanto, uma linguagem humana ) para expressar precisamente os conceitos nos quais Haskell se baseia.

Você pode mostrar um pedaço de código Haskell a qualquer matemático ou lógico, e ele será capaz de entendê-lo, mesmo que nunca tenha ouvido falar de Haskell e não saiba absolutamente nada sobre programação, ciência da computação ou mesmo computadores.

Por outro lado, você pode mostrar a qualquer matemático ou lógico um pedaço de código como este:

x = x + 1

e ele ficará totalmente confuso, dizendo: "Isso não faz sentido, não existe xtal que xseja igual a xmais 1".

Se uma notação específica é ou não "enigmática" ou não, é uma questão de opinião e familiaridade.

Jörg W Mittag
fonte
8
Há apenas um problema com esta resposta: eu não sou matemático.
JohnDoDo
6
@ sepp2k: eu discordo. Para a maioria das pessoas w / o exposição prévia a linguagens de programação e de alguns conhecimentos matemáticos básicos sintaxe Haskell será muito mais simples de entender do que o código procedual típico com todos os seus efeitos secundários e os ambientes complicados declarações são executadas em. Sintaxe como wherepermitir a condensar a essência do uma função em uma linha.
Benjamin Bannier
17
-1: essa resposta parece em grande parte pedante. Estou bastante certo de que o OP significava linguagem falada.
Steven Evers
6
Na verdade, tenho certeza que x = infinityisso realmente resolve a equação.
DeadMG
6
Bem, as linguagens de programação também são projetadas por seres humanos ... Assim, por sua definição, elas são linguagens humanas.
marco-Fiset
13

Eu acho que uma coisa em que você provavelmente está se deparando é algo que eu também encontrei ao aprender programação funcional, que é que, com a programação funcional, você pode (e quase precisa) pensar / trabalhar em um nível mais alto do que na programação imperativa.

O que você acha menos expressivo, acho que é realmente mais expressivo: você não precisa explicar todos os detalhes e pode fazer mais com menos código na programação funcional - há mais poder no que você escreve.

Por exemplo, eu poderia escrever imperativamente:

for each (Person person in people)
    print(person.name)

que é totalmente legível como o inglês.

Uma versão Haskell pode ser (e isso não é válido, mas é apenas para comparação sintática):

map (print . name) people

que requer menos código e menos detalhes - não preciso dividir as coisas em um loop e suas variáveis ​​( for each (...)), a mapfunção cuida disso para mim.

Trabalhar nesse nível pode levar algum tempo para se acostumar. Se isso ajuda, Haskell foi provavelmente o período mais difícil em que aprendi um novo idioma desde que comecei a programar e conheço mais de 10 idiomas (incluindo Lisp). Valeu a pena aprender totalmente.

Paulo
fonte
8

Atualmente, estou começando a lidar com o Scala no momento, para que eu possa simpatizar. Pelo menos com Scala, posso voltar a um estilo imperativo quando as coisas ficam muito difíceis.

Eu acho que há várias forças em jogo aqui:

  • Os projetistas de linguagens funcionais necessariamente têm uma sólida formação em matemática, portanto tomam emprestada a notação matemática que é natural para eles.

  • Maior expressividade (ou seja, poder de declarações, em vez de proximidade com o inglês) de qualquer idioma tem (IMO) um preço correspondente na inclinação da curva de aprendizado. A dispersão é uma qualidade altamente valorizada em Scala, com muitas coisas sendo opcionais.

  • As linguagens funcionais fazem as coisas de maneira muito diferente, para que as operações básicas não sejam mapeadas para construções imperativas.

Richard Close
fonte
3
Eu também acrescentaria que as linguagens funcionais costumam expressar conceitos de ordem superior, sendo mais abstratos, mais difíceis de nomear significativamente
jk.
1
@ jk, sim, concordou! Ao mesmo tempo, é por isso que eles têm uma curva de aprendizado acentuada para programadores com formação imperativa e pouca matemática (como eu), e por que eles valem a pena.
Richard Close
3

Se entendi seu último comentário corretamente, sua pergunta é por que Haskell costuma usar operadores simbólicos em locais onde ele também pode usar palavras-chave alfanuméricas (ou nomes de funções)?

Em relação às palavras-chave, uma resposta seria que elas impedem o uso de determinadas palavras como nomes de variáveis. Por exemplo, eu sempre fico chateado quando quero chamar minhas variáveis frome toem um idioma em que uma delas é uma palavra-chave - como no Python.

Outra razão para operadores simbólicos em geral é a concisão. Isso realmente não se aplica a seus exemplos específicos de compreensão de lista ( <-não é menor que in), mas em muitos casos, é verdade.

Outra razão é a legibilidade. Isso pode parecer contra-intuitivo, porque os operadores simbólicos geralmente são mais difíceis de aprender, já que seus "nomes" realmente não dizem nada sobre o que eles fazem (enquanto o nome de uma função costuma dizer), mas depois que você sabe o que um determinado operador faz, expressões com operadores simbólicos infix costumam ser mais fáceis de analisar para um ser humano do que uma com muitas chamadas de função de prefixo alfanumérico, uma vez que os operadores se distinguem visualmente mais facilmente dos operandos dessa maneira. Por exemplo, a maioria das pessoas concorda que 2 * 3 + 4é mais facilmente legível que add (mult 2 3) 4ou add(mult(2, 3), 4).

sepp2k
fonte
@ PeterTaylor Não, apenas eu sendo estúpido ;-) Corrigido agora.
sepp2k
3

Linguagens de computador imperativas geralmente não estão mais próximas das linguagens naturais do que, digamos, Haskell.

No entanto, alguns são projetados para se parecer mais com o inglês: Cobol e Hypercard, por exemplo. As lições que eu tiraria desses exemplos são:

  • A semelhança com as línguas naturais não parece produzir melhorias diretas na usabilidade
  • a emulação direta de idiomas naturais pode gerar idiomas de computador detalhados e obscuros

A linguagem de computador Perl foi projetada com alguns aspectos mais sutis da linguagem natural em mente . Eu julgaria que o Perl se sai melhor do que o Cobol ou o Hypercard na usabilidade geral, mas as pessoas têm opiniões diferentes sobre o Perl.

tempestade
fonte
3

Acho que Haskell fica tão parecido com a linguagem humana quanto é possível sem introduzir uma sintaxe maluca. Isso realmente faz muito sentido, por exemplo, com a wherecláusula de adiar uma definição e com a sintaxe de compreensão da lista, que é exatamente o que eu escreveria em um quadro negro. Também evita caracteres estranhos, como chaves, e tem um uso liberal de indentação. O exemplo típico é quicksort:

qsort [] = []
qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
               where lesser = [x | x <- xs, x <= p] 
                     greater = [x | x <- xs, x > p]

Admitido, é um exemplo simples, mas não conheço nenhum outro idioma que o deixe tão legível quanto este.

Fazer coisas mais complicadas pode se tornar difícil de ler no Haskell, mas isso tem a ver com o sistema de tipos, o IO restrito e não com a sintaxe.

Na verdade, eu diria que Haskell sacrificou a simplicidade sintática para acomodar uma sintaxe mais semelhante à linguagem humana. Um esquema semelhante a uma linguagem tem uma sintaxe muito distante do que um humano escreveria, mas é realmente simples explicar suas regras.

Andrea
fonte
3
Eu dificilmente chamaria isso de legível por humanos. Eu sei quicksort. Eu estou familiarizado com como configurá-lo em vários idiomas diferentes, sei o que ele deve fazer e ainda não consigo fazer cara ou coroa na metade inferior desse trecho de código.
Mason Wheeler
Eu acho que realmente depende do seu passado. Isto é tão simples quanto ele ganha para mim ...
Andrea
2
Em qualquer caso, é suposto para se assemelhar a esta notação: purplemath.com/modules/setnotn.htm
Andrea
4
Tem certeza de que não deveria ser ++ [p] ++?
Peter Taylor
1
@Mason: Parece bastante claro para mim, e eu nunca escrevi uma linha de Haskell
kevin Cline
2

Eu acho que a diferença tem a ver com a maneira como a programação funcional / declarativa faz declarações sobre um problema como se fosse um problema de matemática, onde a programação imperativa descreve um processo . No mundo dos negócios, os programas de computador envolvem ou substituem processos físicos; portanto, você pode achar uma linguagem que reflete isso mais intuitiva.

Acontece que o estilo funcional se presta ao uso seguro de vários processadores (porque minimiza a mutabilidade e os efeitos colaterais) - algo que veremos mais no futuro. Além disso, as linguagens funcionais mais modernas têm coleções com iteradores para os quais você pode passar funções. Esses métodos podem dividir sua carga de trabalho em vários processadores de maneira muito eficiente, sem que você saiba.

GlenPeterson
fonte
Penso que esta é a melhor resposta - a única que torna clara a distinção entre processo e declarações.
Milind R