Warum kommt die Syntax der funktionalen Sprache der menschlichen Sprache nicht näher?


14

Ich interessiere mich für funktionale Programmierung und habe mich entschieden, mit Haskell in Kontakt zu treten. Mein Kopf tut weh ... aber irgendwann bekomme ich es ... Ich habe eine Kuriosität, warum ist die Syntax so kryptisch (in Ermangelung eines anderen Wortes)?

Gibt es einen Grund, warum es nicht ausdrucksvoller und menschlicher ist?

Ich verstehe, dass FP gut in der Modellierung mathematischer Konzepte ist und einige seiner prägnanten Ausdrucksmittel entlehnt hat, aber es ist immer noch keine Mathematik ... es ist eine Sprache.


4
@ratchet Freak: :) Gibt es also einen, der von einem Typ entworfen wurde, der polnische Notation hasst?
JohnDoDo

10
@ratchetfreak Inwiefern ähnelt die Haskell-Syntax der polnischen Notation? Haskell-Operatoren sind wie die Operatoren der meisten anderen Sprachen Infixe (und Funktionsaufrufe sind Präfixe - wie auch die Funktionsaufrufe der meisten anderen Sprachen).
SEPP2K 05.10.12

9
Das ist eine ziemlich große Annahme, die Sie machen: "Näher an der menschlichen Sprache" ist gleichbedeutend mit "ausdrucksvoller".
Matt Ball

7
Schon mal was von Cobol und Fortran gehört?
ott--

7
Aus genau dem gleichen Grund, aus dem Mathematiker lange lateinische Phrasen durch algebraische Ausdrücke ersetzten. Mit ein wenig Übung ist eine kompaktere Notation viel produktiver.
Kevin Cline

Antworten:


14

Funktionssprachen wie Haskell und seine Vorgängerin Miranda sind aus dem mathematischen Konzept der Lambda-Rechnung hervorgegangen . Von der Wikipedia-Seite:

Der Lambda-Kalkül (auch als λ-Kalkül oder "der Lambda-Kalkül" bezeichnet) ist ein formales System in der mathematischen Logik, um die Berechnung durch Variablenbindung und -substitution auszudrücken.

...

Die Lambda-Rechnung hat eine wichtige Rolle bei der Entwicklung der Theorie der Programmiersprachen gespielt. Die bekanntesten Gegenstücke zum Lambda-Kalkül in der Informatik sind funktionale Programmiersprachen, die im Wesentlichen den Kalkül implementieren (ergänzt mit einigen Konstanten und Datentypen). Über die Programmiersprachen hinaus hat der Lambda-Kalkül auch viele Anwendungen in der Beweistheorie. Ein wichtiges Beispiel hierfür ist die Curry-Howard-Korrespondenz, die eine Korrespondenz zwischen verschiedenen Systemen der typisierten Lambda-Rechnung und Systemen der formalen Logik liefert.

Aufgrund dieser Geschichte wird die Syntax dieser funktionalen Sprachen (und der funktionalen Elemente von imperativeren Sprachen) stark von der mathematischen Notation beeinflusst, die von der Lambda-Rechnung verwendet wird.

Die Genauigkeit, mit der sowohl mathematische Notationen als auch Computersprachen Anforderungen beschreiben können, und die Genauigkeit, mit der Computer ihre Anweisungen schreiben müssen, korrelieren gut miteinander. Die Ungenauigkeit der natürlichen Sprache stellt jedoch eine große Hürde für die Programmierung von Computern dar. Sogar die (wohl) erfolgreichsten Programmierumgebungen für natürliche Sprachen wie Wolfram Alpha benötigen eine beträchtliche Domänenerfahrung, um effektiv eingesetzt zu werden.


29

Die Haskell-Syntax ist der menschlichen Sprache sehr ähnlich. Es ist speziell so konzipiert, dass es der mathematischen Notation ähnelt. Dies ist eine Sprache, die von Menschen entworfen wurde (also eine menschliche Sprache ), um genau die Konzepte auszudrücken, auf denen Haskell aufbaut.

Sie können jedem Mathematiker oder Logiker einen Teil des Haskell-Codes zeigen, und er wird ihn verstehen können, auch wenn er noch nie von Haskell gehört hat und absolut nichts über Programmierung, Informatik oder sogar Computer weiß.

Auf der anderen Seite können Sie jedem Mathematiker oder Logiker einen Code wie diesen zeigen:

x = x + 1

und er wird zutiefst verwirrt sein und sagen: "Das ergibt keinen Sinn, es gibt keinen x, der xgleich xplus ist 1."

Ob eine bestimmte Notation "kryptisch" ist oder nicht, ist eine Frage der Meinung und Vertrautheit.


8
Es gibt nur ein Problem mit dieser Antwort: Ich bin kein Mathematiker.
JohnDoDo

6
@ sepp2k: Ich würde nicht zustimmen. Für die meisten Menschen w / o vor der Exposition gegenüber Programmiersprachen und einig grundlegenden mathematischen Hintergrund wird Haskell Syntax viel einfacher sein als typischer Procedual Code zu verstehen , mit all ihren Nebenwirkungen und den komplizierten Umgebungen Anweisungen ausgeführt werden. Syntax wie whereermöglichen , den Kern zu kondensieren eine Funktion in einer Zeile.
Benjamin Bannier

17
-1: Diese Antwort scheint weitgehend umständlich. Ich bin mir ziemlich sicher, dass das OP die gesprochene Sprache meinte.
Steven Evers

6
Eigentlich bin ich mir ziemlich sicher, dass x = infinitydies tatsächlich die Gleichung löst.
DeadMG

6
Nun, Programmiersprachen werden auch von Menschen entworfen. Nach Ihrer Definition sind sie also menschliche Sprachen.
Marco-Fiset

13

Ich denke, eine Sache, auf die Sie wahrscheinlich stoßen, ist etwas, auf das ich beim Erlernen der funktionalen Programmierung gestoßen bin. Das heißt, dass Sie mit funktionaler Programmierung auf einer höheren Ebene denken / arbeiten können (und fast müssen) als mit imperativer Programmierung.

Was Sie finden , als weniger ausdrucksstark , ich denke , ist eigentlich mehr expressive: Sie müssen nicht jedes kleine Detail darzulegen, und kann mehr mit weniger Code in der funktionalen Programmierung tun - es gibt mehr Kraft auf das, was Sie schreiben.

Zum Beispiel könnte ich unbedingt schreiben:

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

was als Englisch total lesbar ist.

Eine Haskell-Version könnte sein (und dies ist keine gültige Haskell-Version, sondern nur zum syntaktischen Vergleich):

map (print . name) people

Das erfordert weniger Code und weniger Detail-Wrangling. Ich muss die Dinge nicht in eine Schleife und ihre Variablen () aufteilen. for each (...)Die mapFunktion erledigt das für mich.

Das Arbeiten auf diesem Niveau kann gewöhnungsbedürftig sein. Wenn es hilft, war Haskell wahrscheinlich die schwierigste Zeit, in der ich seit Beginn des Programmierens eine neue Sprache gelernt habe, und ich kenne> 10 Sprachen (einschließlich Lisp). Das Lernen hat sich gelohnt.


8

Momentan habe ich es mit Scala zu tun, damit ich mitfühlen kann. Zumindest mit Scala kann ich auf einen imperativen Stil zurückgreifen, wenn es zu schwierig wird.

Ich denke, dass hier mehrere Kräfte im Spiel sind:

  • Designer von funktionalen Sprachen haben notwendigerweise einen starken mathematischen Hintergrund, daher leihen sie sich eine mathematische Notation aus, die für sie selbstverständlich ist.

  • Eine größere Ausdruckskraft (dh Aussagekraft statt Nähe zum Englischen) einer Sprache hat (IMO) einen entsprechenden Preis für die Steilheit der Lernkurve. Knappheit hat in Scala einen hohen Stellenwert, viele Dinge sind optional.

  • Funktionale Sprachen verhalten sich einfach ganz anders, sodass die Grundoperationen nicht auf imperative Konstrukte abgebildet werden.


3
Ich möchte noch hinzufügen, dass oft funktionale Sprachen kann höherer Ordnung Begriffe ausdrücken, wobei diese sind abstrakter, sind schwerer zu Bedeutung nennen
jk.

1
@jk, ja, einverstanden! Gleichzeitig haben sie eine steile Lernkurve für Programmierer mit zwingendem Hintergrund und wenig Mathematik (wie ich) und warum sie sich lohnen.
Richard Close

3

Wenn ich Ihren letzten Kommentar richtig verstanden habe, ist Ihre Frage, warum Haskell häufig symbolische Operatoren an Stellen verwendet, an denen auch alphanumerische Schlüsselwörter (oder Funktionsnamen) verwendet werden könnten.

In Bezug auf Stichwörter würde eine Antwort sein, dass Stichwörter verhindern, dass Sie bestimmte Wörter als Variablennamen verwenden. Zum Beispiel ärgere ich mich immer, wenn ich meine Variablen aufrufen möchte fromund toin einer Sprache, in der eines davon ein Schlüsselwort ist - wie in Python.

Ein weiterer Grund für symbolische Operatoren im Allgemeinen ist die Prägnanz. Das trifft in Ihren spezifischen Beispielen für Listenverständnisse nicht wirklich zu ( <-ist nicht kürzer als in), aber in vielen Fällen schon.

Ein weiterer Grund ist die Lesbarkeit. Dies mag kontraintuitiv erscheinen, da symbolische Operatoren oft schwieriger zu erlernen sind, da ihre "Namen" nicht wirklich Aufschluss darüber geben, was sie tun (wie es der Name einer Funktion normalerweise tut), aber sobald Sie wissen, was ein bestimmter Operator tut, Ausdrücke mit symbolischen Infix-Operatoren sind für einen Menschen oft einfacher zu analysieren als für einen Menschen mit vielen alphanumerischen Präfix-Funktionsaufrufen, da die Operatoren auf diese Weise visuell leichter von den Operanden unterschieden werden können. Zum Beispiel würden die meisten Leute zustimmen, dass dies 2 * 3 + 4leichter lesbar ist als add (mult 2 3) 4oder add(mult(2, 3), 4).


@PeterTaylor Nein, nur ich bin blöd ;-) Jetzt behoben.
SEPP2K

3

Imperative Computersprachen kommen natürlichen Sprachen meist nicht näher als beispielsweise Haskell.

Einige sind jedoch so konzipiert, dass sie dem Englischen ähnlicher sind: zum Beispiel Cobol und Hypercard. Die Lehren, die ich aus diesen Beispielen ziehen würde, sind:

  • Die Ähnlichkeit mit natürlichen Sprachen scheint keine direkten Verbesserungen der Benutzerfreundlichkeit zu bringen
  • Die direkte Emulation natürlicher Sprachen kann zu Computersprachen führen, die ausführlich und undurchsichtig sind

Die Perl-Computersprache wurde Berichten zufolge unter Berücksichtigung einiger subtilerer Aspekte der natürlichen Sprache entwickelt . Ich würde beurteilen, dass Perl in Bezug auf die allgemeine Benutzerfreundlichkeit besser abschneidet als Cobol oder Hypercard, aber die Leute haben unterschiedliche Meinungen über Perl.


3

Ich denke, Haskell wird der menschlichen Sprache so ähnlich, wie man es ohne eine verrückte Syntax erreichen kann. Das geht wirklich sehr weit, zum Beispiel mit der whereKlausel, eine Definition aufzuschieben, und mit der Syntax des Listenverständnisses, die genau das ist, was ich an eine Tafel schreiben würde. Es vermeidet auch unnötige Zeichen wie geschweifte Klammern und verwendet Einrückungen großzügig. Das typische Beispiel ist Quicksort:

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

Zugegeben, es ist ein einfaches Beispiel, aber ich kenne keine andere Sprache, die es so lesbar macht wie diese.

Kompliziertere Dinge zu tun kann in Haskell schwierig werden, aber das hat mit dem Typsystem, dem eingeschränkten IO und überhaupt nicht mit der Syntax zu tun.

Wenn überhaupt, würde ich sagen, dass Haskell syntaktische Einfachheit geopfert hat, um einer Syntax Rechnung zu tragen, die der menschlichen Sprache ähnlicher ist. Ein sprachähnliches Schema hat eine Syntax, die sehr weit von dem entfernt ist, was ein Mensch schreiben würde, aber es ist wirklich einfach, seine Regeln zu erklären.


3
Ich würde das kaum als lesbar bezeichnen. Ich kenne Quicksort. Ich weiß, wie man es in mehreren Sprachen einrichtet, ich weiß, was es tun soll, und ich kann immer noch nicht aus der unteren Hälfte dieses Code-Snippets Kopf oder Zahl machen.
Mason Wheeler

Ich denke, es hängt wirklich von Ihrem Hintergrund ab. Dies ist so klar wie es für mich geht ...
Andrea

2
In jedem Fall sollte es dieser Notation ähneln: purplemath.com/modules/setnotn.htm
Andrea

4
Bist du sicher, dass es nicht sein sollte ++ [p] ++?
Peter Taylor

1
@Mason: Es scheint ziemlich klar zu mir, und ich habe noch nie eine Zeile von Haskell geschrieben
kevin Cline

2

Ich denke, der Unterschied liegt in der Art und Weise, wie funktionale / deklarative Programmierung Aussagen über ein Problem macht, als wäre es ein mathematisches Problem, in dem imperative Programmierung einen Prozess beschreibt . In der Geschäftswelt umschließen oder ersetzen Computerprogramme physische Prozesse, sodass Sie möglicherweise eine Sprache finden, die dies als intuitiver erweist.

Es stellt sich heraus, dass sich der funktionale Stil dazu eignet, mehrere Prozessoren sicher zu verwenden (da er die Veränderlichkeit und die Nebenwirkungen minimiert) - etwas, von dem wir in Zukunft mehr sehen werden. Außerdem verfügen die meisten modernen funktionalen Sprachen über Sammlungen mit Iteratoren, an die Sie Funktionen übergeben können. Diese Methoden können ihre Arbeitslast sehr effizient auf mehrere Prozessoren aufteilen, ohne dass Sie davon etwas wissen.


Ich denke, das ist die beste Antwort - die einzige, die die Unterscheidung zwischen Prozess und Aussagen klar macht.
Milind R
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.