私は関数型プログラミングに興味があり、Haskellと直接対決することにしました。私の頭が痛い...しかし、私は最終的にそれを取得します...しかし、私は1つの好奇心を持っていますが、なぜ構文はとても謎めいています(別の言葉がないのですか)?
それがより表現力がなく、人間の言語により近い理由はありますか?
FPは数学の概念のモデリングが得意であり、簡潔な表現手段の一部を借用していることを理解していますが、それでも数学ではありません...それは言語です。
私は関数型プログラミングに興味があり、Haskellと直接対決することにしました。私の頭が痛い...しかし、私は最終的にそれを取得します...しかし、私は1つの好奇心を持っていますが、なぜ構文はとても謎めいています(別の言葉がないのですか)?
それがより表現力がなく、人間の言語により近い理由はありますか?
FPは数学の概念のモデリングが得意であり、簡潔な表現手段の一部を借用していることを理解していますが、それでも数学ではありません...それは言語です。
回答:
Haskellやその前身であるミランダのような関数型言語は、ラムダ計算の数学的概念から生まれました。ウィキペディアのページから:
ラムダ計算(λ計算または「ラムダ計算」とも呼ばれます)は、変数のバインドと置換によって計算を表現するための数学論理の形式的なシステムです。
...
ラムダ計算は、プログラミング言語の理論の発展に重要な役割を果たしてきました。コンピューターサイエンスのラムダ計算に最もよく対応するのは、関数プログラミング言語です。これは、本質的に計算(いくつかの定数とデータ型で拡張)を実装します。プログラミング言語を超えて、ラムダ計算には証明理論にも多くの用途があります。この主な例は、カリーとハワードの対応です。これは、型付きラムダ計算の異なるシステムと形式論理のシステム間の対応を提供します。
この歴史のため、これらの関数型言語(およびより命令的な言語の関数型要素)の構文は、ラムダ計算で使用される数学表記法に強く影響されます。
数学表記とコンピューター言語の両方が要件を記述できる精度と、コンピューターが命令を記述する必要がある精度は、互いに相関しています。しかし、自然言語の不正確さは、コンピューターのプログラミングに使用する上で大きな障壁となります。Wolfram Alphaのような(ほぼ間違いなく)最も成功した自然言語プログラミング環境でさえも、効果的に使用するにはかなりのドメイン経験が必要です。
Haskell構文は人間の言語に近いです。Haskellが構築されている概念を正確に表現するために人間によって設計された言語(つまり人間の言語)である数学表記に似るように特別に設計されています。
Haskellのコードを数学者や論理学者に見せれば、Haskellのことを聞いたことがなく、プログラミング、コンピューターサイエンス、さらにはコンピューターについてもまったく知らなくても、彼はそれを理解できます。
一方、数学者や論理学者には次のようなコードを見せることができます。
x = x + 1
「何もありません、これは意味がありませんし、彼は全くと言って、混同されx
ているようにx
等しいx
プラス1
。」
特定の表記法が「不可解」かどうかは、意見と親しみの問題です。
where
の要点を凝縮することができます1行の関数。
x = infinity
は確かに方程式を解くと確信しています。
あなたがおそらく遭遇していることの1つは、関数型プログラミングを学ぶときに私が遭遇したことだと思います。つまり、関数型プログラミングでは、命令型プログラミングで行うよりも高いレベルで思考/作業することができます(そしてほとんど必要になります)。
あなたが表現力が低いと思うものは、実際にはより表現力があると思います:あなたは少しずつ詳細を綴る必要はなく、関数型プログラミングのより少ないコードでより多くを行うことができます-あなたが書くものにもっと力があります。
たとえば、私は命令的に書くことができます:
for each (Person person in people)
print(person.name)
これは英語として完全に読みやすいです。
Haskellバージョンは次のようになります(これは有効なHaskellではありませんが、構文の比較のためだけです)。
map (print . name) people
これにより、コードとディテールの問題が少なくなります-ループとその変数に分解する必要はありません(for each (...)
)、map
機能は私のためにそれの世話をします。
そのレベルで作業するには、ある程度慣れる必要があります。それが助けになるとすれば、プログラミングを始めてからHaskellが新しい言語を学んだのはおそらく最も苦労した時期であり、10以上の言語(Lispを含む)を知っています。しかし、学ぶ価値はまったくありました。
現在、私はScalaを理解しているので、同情できます。少なくともScalaを使えば、状況が厳しくなると、命令型のスタイルに戻ることができます。
ここにはいくつかの力が働いていると思います:
関数型言語のデザイナーは必然的に数学のバックグラウンドが強いため、彼らにとって自然な数学的表記法を取り入れています。
あらゆる言語の表現力(つまり、英語に近いというよりは、声明の力)が大きいほど、学習曲線の急峻さに対応する価格が(IMO)あります。簡潔さはScalaで高く評価されている品質であり、多くのオプションがオプションです。
関数型言語は物事を非常に異なる方法で行うため、基本的な操作は命令型の構成要素にマッピングされません。
最後のコメントを正しく理解した場合、あなたの質問は、Haskellが英数字キーワード(または関数名)を使用できる場所でシンボリック演算子をよく使用する理由です。
キーワードに関して、1つの答えは、キーワードが特定の単語を変数名として使用することを妨げるということです。たとえば、変数を呼び出したいときfrom
やto
、Pythonのようにそれらの1つがキーワードである言語では、いつもイライラします。
一般的なシンボリック演算子のもう1つの理由は簡潔さです。リスト内包表記の特定の例には実際には適用されません(<-
より短くはありませんin
)が、多くの場合は適用されます。
さらに別の理由は読みやすさです。シンボリック演算子は「名前」が何をするのかを実際には何も教えてくれないため(関数の名前は通常はわかります)、学ぶのが難しいため、直観に反するように思えるかもしれませんが、与えられた演算子が何をするかを知ったら、中置記号演算子を使用した式は、多くの場合、英数字の接頭辞関数呼び出しを使用した式よりも、演算子がオペランドから視覚的に簡単に区別されるため、人間にとって解析しやすいことがよくあります。たとえば、ほとんどの人は2 * 3 + 4
、add (mult 2 3) 4
またはより簡単に読みやすいことに同意しadd(mult(2, 3), 4)
ます。
命令型コンピューター言語は、ほとんどの場合、Haskellほど自然言語に近くありません。
ただし、一部は、CobolやHypercardなど、より英語に似るように設計されています。これらの例から得られる教訓は次のとおりです。
Perlのコンピューター言語は、自然言語のより微妙な側面を念頭に置いて設計されたと伝えられています。一般的な使いやすさに関しては、PerlはCobolやHypercardよりも優れていると判断しますが、Perlについては意見が異なります。
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は、人間の言語により類似した構文に対応するために、構文の単純さを犠牲にしていると思います。スキームのような言語の構文は、人間が書くものとはかけ離れていますが、そのルールを説明するのは本当に簡単です。
++ [p] ++
ですか?
違いは、関数型/宣言型プログラミングが問題に関するステートメントを作成する方法と関係があると思います。ビジネスの世界では、コンピュータープログラムが物理プロセスをラップまたは置換するため、これを反映した言語がより直感的になることがあります。
機能的なスタイルは、複数のプロセッサを安全に使用するのに適していることがわかります(可変性と副作用を最小限に抑えるため)。また、ほとんどの最新の関数型言語には、関数を渡すことができるイテレータを含むコレクションがあります。これらの方法では、知らないうちにワークロードを複数のプロセッサに非常に効率的に分割できます。