命令型言語は、関数型言語よりも互いにどのように異なるのですか?


17

私はサイモン・ペイトン・ジョーンズの「関数型プログラミング言語の実装」を読んでいますが、私を驚かせた声明が1つあります(39ページ)。

命令型言語の場合よりもはるかに広い範囲で、関数型言語は主に相互の構文上のバリエーションであり、セマンティックの違いは比較的少ないです。

さて、これは1987年に書かれたものであり、この主題に関する私の考えは、当時は普及しておらず人気もなかった、より現代的なプログラミング言語の影響を受ける可能性があります。しかし、これを信じるのは少し難しいと思います。たとえば、記述されているミランダプログラミング言語(Haskellの初期の前身)は、CがPascalに、またはCがsmalltalkにさえ言うよりも、MLのような厳密な言語に比べて、はるかに異なるセマンティクスを持っていると思います(ただし、 C ++は、彼のポイントの検証を提供します:-)。

しかし、もう一度、私はこれを私の直感的な理解に基づいています。サイモン・ペイトン・ジョーンズはこれを言うのに大部分が正しいのでしょうか、またはこれは議論の余地のある点ですか?

回答:


19

サイモンは、拡張的な観点から基本的に正しいです。私たちは現代の関数型言語のセマンティクスが何であるかをよく知っており、それらは実際にはお互いの比較的小さなバリエーションです。Scheme(動的に型付けされた、一流の制御を備えた高次命令型言語)のような言語でさえ、MLとHaskellに非常に近いセマンティクスを持っています。

V

しかし、現代の型付けされた関数型言語の解釈に適したカテゴリーにたどり着くには、非常に怖いものになります。基本的に、このドメインで部分同値関係のウルトラメトリックに強化されたカテゴリを構築することになります。(例として、Birkedal、Stovring、およびThamsborgの「パラメトリック多相性、一般参照、および再帰型の実現可能性セマンティクス」を参照してください。)動作セマンティクスを好む人は、このようなものをステップインデックス付きの論理関係として知っています。(たとえば、Ahmed、Dreyer、およびRossbergの「State-Dependent Representation Independence」を参照してください。)どちらの方法でも、使用される手法は比較的新しいものです。

a -> baTbabTAaa

したがって、等式理論に関する限り、これらの言語はどちらも同じ言語のわずかに異なるサブセットへの翻訳によって記述することができるため、それらを互いに構文のバリエーションと呼ぶのはまったく公平です。

MLとHaskellの感覚の違いは、実際には2つの言語の内包的な特性、つまり実行時間とメモリ消費に起因しています。MLには、本当の名前による呼び出し言語と同様に、合成パフォーマンスモデルがあります(つまり、プログラムの時間/空間コストは、そのサブタームの時間/空間コストから計算できます)。実際のHaskellは、一種のメモ化であるcall-by-needで実装されているため、そのパフォーマンスは構成的ではありません。変数にバインドされた式が評価にかかる時間は、それが以前に使用されたかどうかによって異なります。これは、先ほど触れたセマンティクスではモデル化されていません。

内包的性質をもっと真剣に受けたいのであれば、MLとHaskellはもっと深刻な違いを見せ始めます。それらのために共通のメタ言語を考案することはおそらく可能ですが、型の解釈は、焦点を合わせるという証明理論的な考え方に関連して、はるかに体系的な方法で異なります。これについて学ぶのに適した場所の1つは、Noam Zeilbergerの博士論文です。


10

私の感覚では、SPJは純粋に機能な言語、つまり参照透過的な言語を指していました。これには、たとえば、Haskell、Miranda、Cleanが含まれますが、MLは含まれません。一般に、純粋に機能的な言語ができたら、一般的に、かなりクリーンで明確に定義された表示セマンティクスを与えることができます。このセマンティクスは、一般に、ラムダ計算のように見えますが、あちこちで微調整が行われます。一般に、System Fのバリアントに似たものに脱糖する型システムがあります。おそらく、ある点ではより強力で、他の点ではより制限されています。これが、Haskell、O'Camlなどへのコード抽出/コンパイルが、Agdaなどの洗練された依存型の証明アシスタントから比較的簡単である理由です。

そのフレームワーク内には、遊びの余地がたくさんあります。確かに、厳密でない言語と厳密な言語にはまだ違いがあります。ただし、副作用がない場合、唯一の違いは、非厳密な言語にボトムを示さない表現が含まれていることです。2つの評価戦略の両方がボトムをもたらさない限り、彼らは同意します。

サイモンの発言は、非常に重要な歴史的背景にも当てはまります。Haskell(1987)の誕生の時点では、ミランダだけでなく、Lazy ML、Orwell、Cleanなど、多くの非厳密な関数型言語がありました。特定の構文上の違いを除けば、それらはすべて同じ言語でした。これこそが、Haskell委員会が結成された動機でした。詳細については、「Haskellの歴史:クラスを怠る」:http : //research.microsoft.com/en-us/um/people/simonpj/papers/history-of-haskell/を参照してください。


5

SPJは、コアセマンティクスに対してこれを言うのが正しいと思います。

あなたが言及するように、厳格な評価または怠evaluationな評価のデフォルト設定など、高度な微妙な点が多くありますが、あなたが言及したように、タイプシステムの詳細またはコードのより大きなユニット(モジュール、構造)の編成方法は、プログラムのメンタルモデルです機能言語間で非常に似ています。

特定の特定の関数を選択し、比較するすべての言語で記述します。さまざまな実装の構造とセマンティクスは、抽象レベル、選択したデータ構造、 llはすべてガベージコレクションなどを想定しています。

それどころか、同じ関数のC実装とSmalltalk実装は、異なる構造(関数と低レベルのデータ構造とオブジェクト)を持ち、異なるレベルの詳細(たとえば、手動メモリ管理とガベージコレクション)に焦点を当てると思われます)、および抽象化のさまざまなレベルで動作します。

関数型言語のデザイン空間の世界観は、アセンブリ、C、Smalltalk、Forth、その他多数の根本的に異なる言語を1つのキャッチオールカテゴリにまとめた「命令型プログラミング」空間よりも、より具体的で一貫しています。


4

サイモンPJの引用は実際にはちょっとした言い回しだと思います。

言語間の類似性は、研究者と言語デザイナーのコミュニティでどのようなコンセンサスが生成されたかによって決まります。関数型プログラミングコミュニティでは、命令型プログラミングコミュニティよりも高度なコンセンサスがあることは間違いありません。しかし、関数型プログラミング言語のほとんどが実務者ではなく研究者によって設計されている場合もあります。ですから、そのようなコンセンサスが生まれることは当然です。

ほとんどすべての関数型言語はガベージコレクションメモリ管理と再帰データ構造(Lisp由来)を使用し、それらのほとんどは「代数」データ型とパターンマッチング(Hope由来)を使用し、それらの多くは高階関数と多相関数( MLが発信)。それを超えて、コンセンサスは消えます。それらは、使用されるモジュールシステム、状態変更操作およびその他の計算効果の処理方法、および評価順序(名前による呼び出しと値による呼び出し)などが異なります。

命令型プログラミング言語は、通常、ネストされた制御構造(Algol 60で作成)と型システム(Algol 60で作成されたが、Algol 68で統合)を使用します。それらは一般に面倒な表面構文(再びAlgol 60に戻る)を持ち、高階関数と多態型を処理するために中途半端な試みを行い、ブロック構造とモジュールシステムのサポートが異なります。60年代以降、名前による呼び出しは命令型言語から本質的に姿を消したため、評価順序におそらくより均一性があるでしょう。

そのため、2つのクラスの言語の統一性の違いがそれほど大きいことは私には明らかではありません。

関数型プログラミングの簡潔で統一された表記法を命令型プログラミング言語に組み込むことは本当に価値があります。Scalaがその方向に出発したことがわかります。この傾向が続くかどうかはまだ不明です。


「代数的」なデータ型でなぜ怖い引用符を使用したのか、私は愚かに疑問に思っていますか?
スティーブンショー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.