関数型言語の構文が人間の言語により近いのはなぜですか?


14

私は関数型プログラミングに興味があり、Haskellと直接対決することにしました。私の頭が痛い...しかし、私は最終的にそれを取得します...しかし、私は1つの好奇心を持っていますが、なぜ構文はとても謎めいています(別の言葉がないのですか)?

それがより表現力がなく、人間の言語により近い理由はありますか?

FPは数学の概念のモデリングが得意であり、簡潔な表現手段の一部を借用していることを理解していますが、それでも数学ではありません...それは言語です。


4
@ラチェットフリーク::)だから、ポーランド記法を嫌う男によって設計されたものはありますか?
JohnDoDo

10
@ratchetfreak Haskell構文はどのようにポーランド語表記に似ていますか?Haskell演算子は、他のほとんどの言語の演算子と同様に中置です(関数呼び出しは接頭辞です-他のほとんどの言語の関数呼び出しも同様です)。
sepp2k

9
これはかなり大きな仮定/飛躍であり、「人間の言語により近い」とは「表現力豊か」に等しいということです。
マットボール

7
CobolとFortranを聞いたことがありますか?
-ott--

7
数学者が長いラテン語のフレーズを代数的表現に置き換えたのとまったく同じ理由で。少し練習すれば、よりコンパクトな表記法の方がはるかに生産的です。
ケビンクライン

回答:


14

Haskellやその前身であるミランダのような関数型言語は、ラムダ計算の数学的概念から生まれました。ウィキペディアのページから:

ラムダ計算(λ計算または「ラムダ計算」とも呼ばれます)は、変数のバインドと置換によって計算を表現するための数学論理の形式的なシステムです。

...

ラムダ計算は、プログラミング言語の理論の発展に重要な役割を果たしてきました。コンピューターサイエンスのラムダ計算に最もよく対応するのは、関数プログラミング言語です。これは、本質的に計算(いくつかの定数とデータ型で拡張)を実装します。プログラミング言語を超えて、ラムダ計算には証明理論にも多くの用途があります。この主な例は、カリーとハワードの対応です。これは、型付きラムダ計算の異なるシステムと形式論理のシステム間の対応を提供します。

この歴史のため、これらの関数型言語(およびより命令的な言語の関数型要素)の構文は、ラムダ計算で使用される数学表記法に強く影響されます。

数学表記とコンピューター言語の両方が要件を記述できる精度と、コンピューターが命令を記述する必要がある精度は、互いに相関しています。しかし、自然言語の不正確さは、コンピューターのプログラミングに使用する上で大きな障壁となります。Wolfram Alphaのような(ほぼ間違いなく)最も成功した自然言語プログラミング環境でさえも、効果的に使用するにはかなりのドメイン経験が必要です。


29

Haskell構文人間の言語に近いです。Haskellが構築されている概念を正確に表現するために人間によって設計された言語(つまり人間の言語)である数学表記に似るように特別に設計されています。

Haskellのコードを数学者や論理学者に見せれば、Haskellのことを聞いたことがなく、プログラミング、コンピューターサイエンス、さらにはコンピューターについてもまったく知らなくても、彼はそれを理解できます。

一方、数学者や論理学者には次のようなコードを見せることができます。

x = x + 1

「何もありません、これは意味がありませんし、彼は全くと言って、混同されxているようにx等しいxプラス1。」

特定の表記法が「不可解」かどうかは、意見と親しみの問題です。


8
この答えには1つの問題があります。私は数学者ではありません。
-JohnDoDo

6
@ sepp2k:私は同意しません。ほとんどの人々のために/ Oのプログラミング言語への曝露前といくつかの基本的な数学的背景wはHaskellの構文は、文がで実行されているすべての副作用や複雑な環境での典型的なprocedualコードよりも理解することがはるかに簡単になります。構文のようなwhereの要点を凝縮することができます1行の関数。
ベンジャミンバニエ

17
-1:この答えは大部分がつまらないもののようです。私はOPが話し言葉を意味することをかなり確信しています。
スティーブンエバーズ

6
実際、それx = infinityは確かに方程式を解くと確信しています。
DeadMG

6
さて、プログラミング言語も人間によって設計されています。
marco-fiset

13

あなたがおそらく遭遇していることの1つは、関数型プログラミングを学ぶときに私が遭遇したことだと思います。つまり、関数型プログラミングでは、命令型プログラミングで行うよりも高いレベルで思考/作業することができます(そしてほとんど必要になります)。

あなたが表現力が低いと思うものは、実際にはより表現力があると思います:あなたは少しずつ詳細を綴る必要はなく、関数型プログラミングのより少ないコードでより多くを行うことができます-あなたが書くものにもっと力があります。

たとえば、私は命令的に書くことができます:

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

これは英語として完全に読みやすいです。

Haskellバージョンは次のようになります(これは有効なHaskellではありませんが、構文の比較のためだけです)。

map (print . name) people

これにより、コードとディテールの問題が少なくなります-ループとその変数に分解する必要はありません(for each (...))、map機能は私のためにそれの世話をします。

そのレベルで作業するには、ある程度慣れる必要があります。それが助けになるとすれば、プログラミングを始めてからHaskellが新しい言語を学んだのはおそらく最も苦労した時期であり、10以上の言語(Lispを含む)を知っています。しかし、学ぶ価値はまったくありました。


8

現在、私はScalaを理解しているので、同情できます。少なくともScalaを使えば、状況が厳しくなると、命令型のスタイルに戻ることができます。

ここにはいくつかの力が働いていると思います:

  • 関数型言語のデザイナーは必然的に数学のバックグラウンドが強いため、彼らにとって自然な数学的表記法を取り入れています。

  • あらゆる言語の表現力(つまり、英語に近いというよりは、声明の力)が大きいほど、学習曲線の急峻さに対応する価格が(IMO)あります。簡潔さはScalaで高く評価されている品質であり、多くのオプションがオプションです。

  • 関数型言語は物事を非常に異なる方法で行うため、基本的な操作は命令型の構成要素にマッピングされません。


3
また、関数型言語は高次の概念を表現できる場合が多く、これらはより抽象的であり、意味のある名前を付けるのが難しいということを付け加えます
jk。

1
@jk、はい、同意しました!同時に、それは彼らが命令的な背景と少しの数学(私のような)を持つプログラマーのために急な学習曲線を持っている理由であり、そして彼らが価値がある理由です。
リチャードクローズ

3

最後のコメントを正しく理解した場合、あなたの質問は、Haskellが英数字キーワード(または関数名)を使用できる場所でシンボリック演算子をよく使用する理由です。

キーワードに関して、1つの答えは、キーワードが特定の単語を変数名として使用することを妨げるということです。たとえば、変数を呼び出したいときfromto、Pythonのようにそれらの1つがキーワードである言語では、いつもイライラします。

一般的なシンボリック演算子のもう1つの理由は簡潔さです。リスト内包表記の特定の例には実際には適用されません(<-より短くはありませんin)が、多くの場合は適用されます。

さらに別の理由は読みやすさです。シンボリック演算子は「名前」が何をするのかを実際には何も教えてくれないため(関数の名前は通常はわかります)、学ぶのが難しいため、直観に反するように思えるかもしれませんが、与えられた演算子が何をするかを知ったら、中置記号演算子を使用した式は、多くの場合、英数字の接頭辞関数呼び出しを使用した式よりも、演算子がオペランドから視覚的に簡単に区別されるため、人間にとって解析しやすいことがよくあります。たとえば、ほとんどの人は2 * 3 + 4add (mult 2 3) 4またはより簡単に読みやすいことに同意しadd(mult(2, 3), 4)ます。


@PeterTaylor Nope、ただ私が愚かです;-)今修正されました。
sepp2k

3

命令型コンピューター言語は、ほとんどの場合、Haskellほど自然言語に近くありません。

ただし、一部は、CobolやHypercardなど、より英語に似るように設計されています。これらの例から得られる教訓は次のとおりです。

  • 自然言語との類似性は、ユーザビリティの直接的な改善をもたらさないようです
  • 自然言語を直接エミュレートすると、冗長であいまいなコンピューター言語が生成される可能性があります

Perlのコンピューター言語は、自然言語のより微妙な側面を念頭に置いて設計されたと伝えられています。一般的な使いやすさに関しては、PerlはCobolやHypercardよりも優れていると判断しますが、Perlについては意見が異なります。


3

Haskellは、クレイジーな構文を導入しなくても取得できるのと同じくらい人間の言語に似ていると思います。たとえばwhere、定義を延期するための句や、黒板に書かれているとおりのリスト内包構文を使用することで、これは非常に長くなります。また、中括弧などの無関係な文字を避け、インデントを自由に使用します。典型的な例はクイックソートです:

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

確かに、これは簡単な例ですが、これほど読みやすい言語になっている他の言語は知りません。

Haskellでは、より複雑なことを行うのが難しくなる場合がありますが、それは構文ではなく、型システム、制約されたIOに関係しています。

どちらかといえば、Haskellは、人間の言語により類似した構文に対応するために、構文の単純さを犠牲にしていると思います。スキームのような言語の構文は、人間が書くものとはかけ離れていますが、そのルールを説明するのは本当に簡単です。


3
私はそれを人間が読めるとはほとんど呼びません。クイックソートを知っています。私は複数の異なる言語でそれを設定する方法に精通しており、それが何をすべきかを知っていますが、まだコードスニペットの下半分から頭や尾を作ることはできません。
メイソンウィーラー

本当にあなたの背景に依存していると思います。それは私のためになるように、これは...平野ようです
アンドレア・

2
いずれにせよ、それはこの表記法に似ているはずです:purplemath.com/modules/setnotn.htm
アンドレア

4
すべきではないの++ [p] ++ですか?
ピーターテイラー

1
@メイソン:それは私にはかなり明らかなようだ、と私はハスケルの行を書いたことがない
ケビンクライン

2

違いは、関数型/宣言型プログラミングが問題に関するステートメントを作成する方法と関係があると思います。ビジネスの世界では、コンピュータープログラムが物理プロセスをラップまたは置換するため、これを反映した言語がより直感的になることがあります。

機能的なスタイルは、複数のプロセッサを安全に使用するのに適していることがわかります(可変性と副作用を最小限に抑えるため)。また、ほとんどの最新の関数型言語には、関数を渡すことができるイテレータを含むコレクションがあります。これらの方法では、知らないうちにワークロードを複数のプロセッサに非常に効率的に分割できます。


これが最良の答えだと思います-プロセスとステートメントの区別を明確にする唯一の答えです。
Milind R 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.