関数型プログラミングは、問題と解決策の間の「代表的なギャップ」を増やしますか?[閉まっている]


18

機械言語(例:)は、0110101000110101一般にコンピューター言語がより高度な抽象化に進化してきたため、一般的に問題に適用されたときにコードを理解しやすくします。アセンブラーはマシンコードの抽象化であり、Cはアセンブラーの抽象化などでした。

オブジェクト指向設計は、オブジェクトの観点から問題をモデル化するのに非常に優れているようです。たとえば、大学の履修登録システムの問題は、Courseクラス、Studentクラスなどでモデル化できます。 OO言語では、責任を負う同様のクラスがあり、一般に設計、特にコードのモジュール化に役立ちます。この問題をOOメソッドで解決する10の独立したチームに与えた場合、通常、10のソリューションには共通して問題に関連するクラスがあります。これらのクラスの結合と相互作用を開始し始めると、多くの違いが生じる可能性があるため、「表現のギャップがゼロ」というものはありません。

関数型プログラミングの私の経験は非常に限られています(実際の使用はなく、Hello Worldタイプのプログラムのみ)。このような言語がOO言語のようにFPソリューションを問題に(低い表現のギャップで)簡単にマッピングできるようにする方法を私は見ていません。

並行プログラミングに関するFPの利点を理解しています。しかし、私は何かを逃していますか、またはFPは表現のギャップを減らすことではありませんか?

これを尋ねる別の方法:同じ現実の問題を解決する10の異なるチームのFPコードには多くの共通点がありますか?


抽象化に関するウィキペディア(コンピューターサイエンス)から(強調鉱山):

関数型プログラミング言語は一般に、ラムダ抽象化(用語を変数の関数にする)、高次関数(パラメーターは関数)、ブラケット抽象化(用語を変数の関数にする)など、関数関連する抽象化を示します。

[一部の]実際の問題はこのような抽象化では簡単にモデル化されないため、表現のギャップは潜在的に拡大する可能性があります。


表現のギャップを減らすもう1つの方法は、ソリューション要素を問題にまでさかのぼることです。0さんと1マシンコードでSは一方で、バックトレースすることは非常に困難であるStudentクラスは、トレースバックに簡単です。すべてのOOクラスが問題空間に簡単にトレースできるわけではありませんが、多くのクラスがトレースしています。

FPの抽象化は、常に彼らが(離れてから解決されている問題空間のどの部分を見つけるために説明する必要はありません数学の問題)?OK-私はこの部分でいいです。さらに多くの例を見ると、FPの抽象化がデータ処理で表現される問題の一部に対して非常に明確であることがわかります。


関連する質問に対する受け入れられた回答UMLは、機能プログラムのモデル化に使用できますか?-「機能プログラマーは、ダイアグラムをあまり使いません」と言います。それがUMLであるかどうかは本当に気にしませんが、広く使用されているダイアグラムがない場合、FPの抽象化が簡単に理解/通信できるかどうか疑問に思います(この答えが正しいと仮定して)。繰り返しになりますが、FPの使用/理解のレベルはささいなものなので、単純なFPプログラムのダイアグラムの必要はないと理解しています。

OOデザインには、機能/クラス/パッケージレベルの抽象化があり、それぞれにカプセル化(アクセス制御、情報隠蔽)があり、複雑さの管理を容易にします。これらは、問題から解決策へと簡単に戻ることができる要素です。


多くの答えは、オブジェクト指向に類似した方法でFPで分析と設計が行われる方法について述べていますが、これまで高レベルのものを引用する人はいません(paulはいくつかの興味深いものを引用しましたが、低レベルです)。昨日はグーグルで多くのことをして、興味深い議論を見つけました。以下は、サイモン・トンプソンによるリファクタリング機能プログラムからのものです(2004)(強調の鉱山)

オブジェクト指向システムの設計では、プログラミングよりも設計が優先されることは当然のことです。デザインは、EclipseなどのツールでサポートされているUMLのようなシステムを使用して作成されます。初心者のプログラマーは、BlueJのようなシステムを使用して視覚的な設計アプローチを学ぶことができます。関数型プログラミングのための同様の方法論に関する作業がFAD:Functional Analysis and Designで報告されていますが、他の作業はほとんどありません。これにはいくつかの理由があります。

  • 既存の機能プログラムは、設計を必要としない規模です。多くの機能プログラムは小さいですが、Glasgow Haskell Compilerなどの他のプログラムはかなりのものです。

  • 機能プログラムはアプリケーションドメインを直接モデル化するため、デザインは無関係になります。関数型言語はさまざまな強力な抽象化を提供しますが、これらが現実世界をモデル化するために必要なすべての抽象化のみを提供すると主張することは困難です。

  • 機能プログラムは、進化する一連のプロトタイプとして構築されます。

上記引用され博士論文では、分析と設計の方法論(ADM)を使用する利点が、パラダイムとは無関係に概説されています。しかし、ADMは実装パラダイムと整合する必要があるという主張がなされています。つまり、OOADMはOOプログラミングに最適であり、FPなどの別のパラダイムにはあまり適用されません。これは、私が表現ギャップと呼ぶものを言い換えていると思う素晴らしい引用です:

どのパラダイムがソフトウェア開発に最適なサポートを提供するかについては長々と議論できますが、問題の説明から実装および配信まで単一のパラダイム内にとどまると、最も自然で効率的かつ効果的な開発パッケージを実現できます。

FADが提案する一連の図を次に示します。

  • 実装で使用する関数を関数に提示する関数依存図。
  • 型に同じサービスを提供する型依存図。そして、
  • システムのモジュールアーキテクチャのビューを表示するモジュール依存関係図。

FAD論文のセクション5.1にはケーススタディがあります。これは、フットボール(サッカー)リーグに関連するデータの生成を自動化するシステムです。要件は100%機能的です。たとえば、サッカーの結果の入力、リーグテーブルの作成、得点表、出欠表、チーム間での選手の移動、新しい結果の後のデータの更新などです。 、「新しい機能は最小限のコストで許可する必要がある」と述べることは別として、テストすることはほぼ不可能です。

悲しいことに、FADを除いて、FP用に提案されているモデリング言語(視覚)の最新の参照はありません。UMLは別のパラダイムなので、それを忘れてください。


1
コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
maple_shaft

回答:


20

基本データは、ほとんどすべてのパラダイムで同じように構造化されています。あなたは、必要があるとしているStudentCourseそれはオブジェクト、構造体、記録、または任意のかどうか、などを。OOPとの違いは、データの構造ではなく、関数の構造です。

実際、機能プログラムは、問題に対する考え方と非常によく一致しています。たとえば、次の学期の学生のスケジュールを計画するには、学生が完了したコースのリスト、学生の学位プログラムのコース、この学期に提供されたコース、学生が前提条件を満たしたコース、時間のないコースなどを考えます競合などしない

突然、どのクラスがこれらすべてのリストを作成して保存する必要があるかは、それほど明確ではありません。これらのリストの複雑な組み合わせがある場合はさらに少なくなります。ただし、1つのクラスを選択する必要あります。

FPでは、学生とコースのリストを取得し、フィルターされたコースのリストを返す関数を作成します。このようなすべての機能をモジュールにまとめることができます。あるクラスや別のクラスと組み合わせる必要はありません。

そのため、データモデルは、他のクラスの組み合わせで動作する関数を配置する便利な場所を提供する以外の目的を持たないクラスで汚染される前に、OOPプログラマーがモデルをどのように考えるかに似るようになります。CourseStudentFilterListOOPで常に必要になる奇妙なクラスや類似したクラスはありませんが、最初の設計では考えないでください。


5
私の経験で問題はその後、学生に関連する機能は、Studentクラスに追加されていることであり、その責任は成長し、あなたが紹介する必要があるまで成長@BenAaronson StudentCourseFilterer管理しやすいものを維持するために
AlexFoxGill

3
@Den Hybridアプローチにはメリットがあります。しかし、区別が人為的であることは真実ではありません。ScalaはフィットOOPとFP(それほど強力型推論が1であるためにしなければならなかった妥協がたくさんある複雑さは別である:はい、ミックスOOPとFPはよりになる傾向があることを言語。複合体は -使用する「ハードのようにそして、理解します」-より純粋な兄弟の1つより、両極端)。
アンドレスF.

3
@Den Erik Meijerの「 'Mostly Functional' programming does not work」も参照してください。これは、ハイブリッドアプローチに反対し、完全な「ファンダメンタリスト」FPを主張します。
アンドレスF.

4
@Denあなたが説明する人気は、歴史の偶然です。私は職場でScalaを使用していますが、FPとOOPを混在させようとするため、Scalaは複雑な獣です。Haskellのような真のFP言語に切り替えることは、新鮮な空気の息吹のように感じます-そして、私も学問の観点から話をしていません!
アンドレスF.

3
@Denこれらの関数のどちらが何をするのかわかりません。FPの最初の関数は、ソートやフィルタした場合しかし、私はあなたを伝えることができ、命名されるだろうフィルタソート、ないfunc(あなたがそれを名前のと同じようにIFilterなど、)。一般的に、FPでは名前を付けるfuncf、どちらかsortまたはfilter有効な選択肢を選択します。たとえばfunc、パラメーターとして受け取る高階関数を作成する場合。
アンドレスF.

10

私が数年前にJavaクラスを受講したとき、クラス全体にソリューションを示すことが期待されていたため、人々がどのように考えているかを見ることができました。論理的に問題を解決する方法。3つまたは4つの一般的なソリューションを中心にクラスター化するソリューションを完全に期待していました。代わりに、30人の学生が30のまったく異なる方法で問題を解決するのを見ました。

当然、未熟なプログラマーが経験を積むにつれて、共通のソフトウェアパターンにさらされ、コードでそれらのパターンの使用を開始し、その後、ソリューションがいくつかの最適な戦略に合体する可能性があります。これらのパターンは、経験豊富な開発者がコミュニケーションできる技術的な言語を形成します。

関数型プログラミングを支える技術言語は数学です。したがって、関数型プログラミングを使用して解決するのに最も適した問題は、本質的に数学の問題です。 数学では、足し算や引き算のようなビジネスソリューションで見られるような数学のことではありません。むしろ、私は、Math Overflowで表示される可能性のある数学の種類、またはOrbitzの検索エンジン(Lispで記述されている)で表示される数学の種類について話しています。

このオリエンテーションには、実世界のプログラミングの問題を解決しようとする機能プログラマーにとって、いくつかの重要な影響があります。

  1. 関数型プログラミングは命令型よりも宣言型です。それは、それを行う方法ではなく、主にコンピュータに何をするかを伝えることに関係しています。

  2. 多くの場合、オブジェクト指向プログラムはトップダウンで構築されます。クラス設計が作成され、詳細が入力されます。機能プログラムは、多くの場合、ボトムアップから構築され、小規模で詳細な機能が上位レベルの機能に結合されます。

  3. 関数型プログラミングには、複雑なロジックのプロトタイピング、有機的に変更および進化できる柔軟なプログラムの構築、初期設計が不明確なソフトウェアの構築に利点があります。

  4. クラス、オブジェクト間のメッセージ、およびソフトウェアパターンはすべて、ビジネスドメインにマップし、ビジネスインテリジェンスをキャプチャし、それを文書化する構造を提供するため、オブジェクト指向プログラムはビジネスドメインにより適しています。

  5. すべての実用的なソフトウェアは副作用(I / O)を生成するため、純粋に関数型のプログラミング言語では、数学的に純粋(モナド)のままでこれらの副作用を生成するメカニズムが必要です。

  6. 関数型プログラムは、数学的な性質があるため、より簡単に証明できます。Haskellの型システムは、コンパイル時にほとんどのOO言語ではできないものを見つけることができます。

等々。コンピューティングにおける多くのことと同様に、オブジェクト指向言語と関数型言語には異なるトレードオフがあります。

いくつかの最新のOO言語は、便利な関数型プログラミングの概念のいくつかを採用しているため、両方の長所を活用できます。Linq、およびそれをサポートするために追加された言語機能は、その良い例です。


6
@thepacker:関数型プログラミングには状態があります。表現のみが異なります。OOPでは可変変数を使用しますが、関数型プログラミングでは、プログラムが検査する必要があるときにオンザフライで作成される状態の無限ストリームを使用できます。残念ながら、状態は可変変数で識別されることがよくあります。これは、可変変数が状態を表現する唯一の方法であるかのようです。結果として、多くの人は、可変変数のないプログラミング言語では状態をモデル化できないと考えています。
ジョルジョ

12
「したがって、関数型プログラミングを使用して解決するのに最も適した問題は、本質的に数学の問題です。」:私はこの声明に同意しません(以前のコメントも参照)。実際に意味します。ディレクトリ構造をトラバースすることは数学の問題であり、再帰関数を使用して実装することができますが、顧客にはソースコードが表示されないため、ファイルシステム内のどこかでファイルを見つけるなどの実際的な問題を解決しているだけです。数学の問題と数学以外の問題の違いは人為的です。
ジョルジオ

5
+1、しかし私はポイント2と4で販売されていません。トップダウンで問題に取り組み、すべてのタイプと操作を定義することから始まる多くのHaskellチュートリアルとブログ投稿を見てきました。すべての値と関数定義を未定義のままにします(まあ、例外をスローするように定義されています)。Haskellのプログラマが問題をモデル化する傾向があるように私には思えるより徹底的例えば追加-彼らはより多くのセマンティクスのために些細なタイプを追加するために傾いているのでSafeString、一般の多くのトラックを維持する- HTMLエスケープされている文字列を表現するためにタイプをエフェクト。
ドーバル

4
「関数型プログラミングを使用して解決するのに最も適した問題は、本質的に数学の問題です。」それは単に真実ではありません。モナドの概念がカテゴリー理論に由来するという事実は、数学的なタスクが関数型言語の最も自然/適合領域であることを意味するものでもありません。つまり、厳密に型指定された関数型言語で記述されたコードは、数学の使用について記述、分析、および推論できるということです。これは強力な追加機能であり、Haskellで「Barbie Horse Adventures」を書くのを止めるものではありません。
itsbruce

6
@itsbruce Barbie Horse Adventuresは、最高の口径の本格的な数学的シミュレーションです。それは、人々を納得させるさまざまな現実の世界環境でバービーの髪の物理的な揺らめきを記述するマトリックスのような過度に複雑な数値投影にFPを保持するピジョンです毎日のビジネス問題のコーディングとは無関係であるとして完全に却下します。
ジミーホファ

7

私が重要だと思う側面を強調したいと思いますが、それは他の答えではカバーされていません。

まず第一に、問題と解決策の間の表現のギャップは、プログラマーの背景と、彼らがより精通している概念に応じて、プログラマーの心の中でより大きくなると思います。

OOPとFPは、2つの異なる観点からデータと操作を調べ、ロバートハーベイが既に指摘したように、異なるトレードオフを提供します。

それらが異なる1つの重要な側面は、ソフトウェアを拡張する方法です。

たとえば、さまざまな画像形式があり、画像を処理するアルゴリズムのライブラリを保持しているなど、データ型のコレクションと操作のコレクションがある状況を考えてください。

関数型プログラミングを使用すると、ソフトウェアに新しい操作を簡単に追加できます。コードをローカルに変更するだけです。つまり、異なる入力データ形式を処理する新しい関数を追加するだけです。一方、新しい形式の追加はより複雑です。すでに実装しているすべての機能を変更する必要があります(ローカルな変更ではありません)。

オブジェクト指向のアプローチはこれと対称的です。各データ型はすべての操作の独自の実装を実行し、実行時に適切な実装を選択する責任があります(動的ディスパッチ)。これにより、新しいデータ型(新しい画像形式など)を簡単に追加できます。新しいクラスを追加して、そのすべてのメソッドを実装するだけです。一方、新しいオペレーションを追加すると、そのオペレーションを提供する必要があるすべてのクラスを変更することになります。多くの言語では、これはインターフェイスを拡張し、それを実装するすべてのクラスを適応させることにより行われます。

拡張に対するこの異なるアプローチは、操作のセットがこれらの操作が機能するデータ型のセットよりも頻繁に変化しない特定の問題に対してOOPがより適切である理由の1つです。典型的な例は、GUIです:あなたはすべてのウィジェットを実装しなければならないことを事業の固定セット(持っているpaintresizemove、など)とあなたが拡張したいというウィジェットのコレクションを。

したがって、この次元によれば、OOPとFPは、コードを整理する2つのスペキュラー方法にすぎません。SICP、特にセクション2.4.3、表2.22、および段落メッセージの受け渡しを参照してください。

要約:OOPではデータを使用して操作を整理し、FPでは操作を使用してデータを整理します。各アプローチは、コンテキストに応じてより強くまたはより弱くなります。一般に、2つとも問題と解決策の間に高い表現上のギャップはありません。


1
実際、(OOPの)訪問者パターンは、FPについて述べたのと同じパワーを提供します。これにより、新しいクラスを追加するのを難しくしながら、新しい操作を追加できます。FPで同じことができるかどうか(たとえば、操作の代わりに新しい形式を追加する)。
陶酔感

1
画像処理のシナリオは、最良の例とは思えません。確かに、画像を何らかの内部形式に変換し、それを処理して、画像タイプごとにすべての画像処理スタッフの個別の実装を記述することはありませんか?
ヘイ

1
@Giorgioは、この部分から意図した意味を得ていないかもしれません。「新しいフォーマットの追加はより複雑です。すでに実装したすべての機能を変更する必要があります。」
ヘイ

2
@Hey Giorgioは、いわゆるExpression Problemに言及している可能性があります。「新しい形式を追加する」とは、「データ型に新しいコンストラクター(別名「ケース」)を追加する」ことを意味します。
アンドレスF.

1
@Euphoric:詳細については検討していませんが、FPの訪問者パターンに対応するものにはOther、データ型のバリアント/コンストラクターと、他のケースを処理するためにすべての関数に渡される追加の関数パラメーターが必要です。もちろん、OOPソリューション(動的ディスパッチ)に関しては不自然で不自然です。同様に、ビジターパターンは、FPソリューションよりも不自然で不自然です(高次関数)。
ジョルジオ

5

ほとんどの関数型言語はオブジェクト指向ではありません。それは、それらにオブジェクトがないという意味ではありません(特定の機能が関連付けられている複雑なタイプの意味で)。Haskellは、javaと同様に、リスト、マップ、配列、あらゆる種類のツリー、および他の多くの複雑なタイプを持っています。Haskellリストまたはマップモジュールを見ると、ほとんどの同等のOO言語ライブラリモジュールのメソッドに非常によく似た一連の関数が表示されます。コードを調べると、いくつかのタイプ(正確にはコンストラクター)と、モジュール内の他の関数でのみ使用可能な関数を使用した同様のカプセル化も見つかります。

Haskellでこれらのタイプを扱う方法は、多くの場合、OOの方法とほとんど変わりません。ハスケルで言う

  null xs
  length xs

そしてJavaではあなたは言う

  xs.isEmpty
  xs.length

トマト、トマト。Haskell関数はオブジェクトに関連付けられていませんが、そのタイプに密接に関連付けられています。¨Ah、しかし、¨あなたは言います¨Javaでは、そのオブジェクトの実際のクラスに適切な長さのメソッドを呼び出しています¨ 驚き-Haskellは、型クラス(およびその他のもの)でもポリモーフィズムを行います。

Haskellでは、私が持っている場合である -整数の集合-それは、コレクションは、このコードは、リストまたはセットまたは配列であるかは重要ではありません

  fmap (* 2) is

すべての要素が2倍になったコレクションを返します。多態性とは、特定のタイプに適切なマップ関数が呼び出されることを意味します。

実際、これらの例は実際には複雑なタイプではありませんが、より難しい問題にも同じことが当てはまります。関数型言語では複雑なオブジェクトをモデル化したり、特定の機能をそれらに関連付けたりできないという考えは、単に間違っています。

あります、機能とOOスタイルの間に重要と有意差はなく、私はこの答えはそれらに対処するために持っていると思うドント。関数型言語が、問題やタスクの直感的なモデリングを妨げる(または妨げる)かどうかを尋ねました。答えはいいえだ。


実際のところ、Java / C#で型クラスを使用できます。コンパイラに型に基づいて正しい辞書を推測させるのではなく、関数の辞書を明示的に渡すだけです。
ドーバル

ああ、間違いなく。ウィリアムクックが言ったように、多くのオブジェクト指向コードは、実際にはコーダーが認識していない場合でも、機能コードよりも高次関数を頻繁に使用します。
itsbruce

2
あなたは間違った区別をしています。リストは、スタック、キュー、三目並べシミュレータと同じように、不活性なデータ構造ではありません。リストは何でも保持でき(Haskellでは部分的に適用された関数である可能性があります)、それらのものとやり取りする方法を定義します。部分的に適用された関数の完全なリストを別の値のリストに適用すると、結果は、最初の関数と2番目の関数の入力のすべての可能な組み合わせを含む新しいリストになります。これは、C構造体以上のものです。
-itsbruce

3
関数型言語では、型は命令型/オブジェクト指向言語よりもさまざまなものに使用されます(1つには、型システムがより強力で一貫している傾向があります)。たとえば、タイプとその関数は、コードパスを形成するために使用されます(これが、いくつかの関数型言語が単にループのキーワードを持たない理由です-不要です)。
itsbruce

4
@Fuhrmanator「これがFPでどのように行われているのか見ていません」あなたは理解していないことを文句を言うのは意味がありません。それを学びに行き、徹底的に理解すれば、それは理にかなっています。おそらくそれが理にかなった後、あなたはそれががらくたであると判断し、あなたにそれを証明するために他の人を必要としないでしょうが、上記のような他の人はそれを理解し、その結論に至っていません。あなたは銃の戦いにナイフを持っているように見えます、そして今、あなたは銃が鋭くないので役に立たないことを皆に言っています。
ジミーホファ

4

FPは、実際、表現のギャップの縮小に努めています。

関数型言語でよく目にするのは、言語を(ボトムアップデザインを使用して)組み込みドメイン固有言語(EDSL)に構築する方法です。これにより、プログラミング言語内でドメインにとって自然な方法でビジネス上の懸念を表現する手段を開発できます。HaskellとLispはどちらもこのことに誇りを持っています。

この機能を可能にするものの一部(すべてではないが)は、基本言語内での柔軟性と表現力です。ファーストクラス関数、高階関数、関数合成、および一部の言語では、代数データ型(差別化されたユニオンとも呼ばれます)および演算子を定義する機能*により、OOPを使用する場合よりも柔軟に表現することができます。あなたはおそらくあなたの問題の領域から物事を表現するより自然な方法を見つけることを意味します。(多くのOOP言語が最近これらの機能の多くを採用しているということを言うべきです。

*はい、多くのOOP言語では標準演算子をオーバーライドできますが、Haskellでは新しい演算子を定義できます!

関数型言語(主にF#とHaskell、一部のClojure、および少しのLispとErlang)を使用した私の経験では、OOPを使用するよりも、特に代数的データ型を使用して、問題空間を言語にマッピングするのが簡単ですクラスよりも柔軟だと思います。FP、特にHaskellで始めたときにループを引き起こしたのは、命令型言語やOOP言語で慣れていたよりも少し高いレベルで考えたり作業したりする必要があったことです。あなたもこれに少し走っているかもしれません。


(顧客からの)ビジネス上の懸念は、高階関数ではあまり表れません。ただし、顧客は1行のユーザーストーリーを記述してビジネスルールを提供できます(または、顧客からそれらを取り出すことができます)。(トップダウン?)ドメインモデリング(これらのアーティファクトから)に興味があります。これにより、一流の関数などにマップされる問題の抽象化に到達できます。ドメイン、抽象化などの具体例を使用できますか?
-Fuhrmanator

3
@Fuhrmanator OOPとFPを使用するかどうかに関係なく、顧客は1行のユーザーストーリーとビジネスルールを記述することができます。継承、構成、またはインターフェースを理解することを期待する以上に、顧客が高階関数を理解することは期待していません。
アンドレスF.

1
@Fuhrmanatorどのくらいの頻度で、Javaジェネリックまたは抽象基本クラスとインターフェースに関して顧客に懸念を表明させましたか?ディア・ゴッド。ポールはあなたに非常に良い答えを与えました。確かに視覚化するのが難しくないテクニックを使った実用的で信頼できるモデリングの方法を説明しています。しかし、あなたはそれが特定のパラダイムのための特定のモデリング技術の観点から説明されることを主張します。あたかもそれがデザインやその他の表現を表現する最も自然な方法であるかのように
-itsbruce

@Fuhrmanatorこれは、あなたが探しているような高レベルとしてではないかもしれませんが、機能の技術を使用して、設計プロセスにいくつかの洞察力を与える必要があります。設計に型を持ちます。いくつかの優れた記事があるので、一般にそのサイトを閲覧することをお勧めします。
ポール

@FuhrmanatorこのThinking Functionallyシリーズもあります
ポール

3

Niklaus Wirthが言うように、「アルゴリズム+データ構造=プログラム」。関数型プログラミングはアルゴリズムを整理する方法に関するものであり、データ構造を整理する方法についてはあまり語りません。実際、可変(Lisp)変数と不変(Haskell、Erlang)変数の両方を持つFP言語が存在します。FPを何かと比較対照する場合は、命令型(C、Java)および宣言型(Prolog)プログラミングを選択する必要があります。

一方、OOPはデータ構造を構築し、それらにアルゴリズムを付加する方法です。FPは、OOPのようなデータ構造の構築を妨げません。あなたが私を信じていないなら、Haskellの型宣言を見てください。ただし、ほとんどのFP言語では、関数はデータ構造に属しておらず、同じ名前空間にある必要があることに同意しています。これは、関数合成による新しいアルゴリズムの構築を簡素化するために行われます。確かに、関数がどの入力を受け取り、どの出力を生成するかを知っている場合、なぜそれがどのデータ構造に属しているのかが重要なのでしょうか?たとえばadd、整数型のインスタンスで関数を呼び出して、2つの整数引数を単に渡すのではなく、引数を渡す必要があるのはなぜですか?

したがって、FPがソリューションを一般的に理解しにくくする必要がある理由がわかりません。とにかくそれが実現するとは思いません。ただし、経験豊富な命令型プログラマーは、関数型プログラムを命令型プログラムよりも理解するのが難しく、逆もまた同様であることを忘れないでください。これはWindowsに似ています-Windows環境に慣れるために10年を費やした人々が1か月の使用後にLinuxを困難にし、Linuxに慣れている人々がWindowsで同じ生産性を達成できない場合のLinuxの二分法。したがって、あなたが話している「代表的なギャップ」は非常に主観的です。


OOの原則そのものではないカプセル化とデータの非表示のため、OOがデータ構造+アルゴリズム(内部ビューのみ)であることには完全に同意しません。優れた抽象化の利点は、多くの詳細を理解する必要なく、問題の一部を解決するために提供するサービスがあることです。FPで関数とデータを分離するとき、カプセル化について話していると思いますが、私は確実に知るにはあまりにもグリーンです。また、ソリューションから問題までさかのぼってトレースするように質問を編集しました(表現のギャップの意味を明確にするため)。
-Fuhrmanator

if you know what input a function takes and what output it produces, why should it matter which data structure it belongs too?これはまとまりのように聞こえますが、これはモジュラーシステムにとって重要です。関数を見つける場所がわからないと、ソリューションの理解が難しくなります。これは、表現のギャップが大きいためです。多くのオブジェクト指向システムにはこの問題がありますが、それはデザインが悪い(凝集度が低い)ためです。繰り返しになりますが、名前空間の問題はFPの専門知識が不足しているため、見た目ほど悪くないかもしれません。
-Fuhrmanator

1
@Fuhrmanatorしかし、あなた関数を見つける場所を知っています。また、各データ型に対して定義された同じ名前の複数の関数ではなく、1つの関数のみがあります(再び、「式の問題」を参照)。たとえば、Haskellライブラリ関数(ホイールを再発見したり、上記の関数のやや有用性の低いバージョンを作成する代わりに使用することをお勧めします)の場合、Hoogleなどの素晴らしい発見ツールがあり、検索が非常に強力です署名(試してみてください!:))
アンドレスF.

1
@Fuhrmanator、「それはまとまりのように聞こえます」の後、FP言語ではよりまとまりのあるプログラムを作成できると論理的に結論付けられると期待していましたが、あなたは私を驚かせました。:-) FP言語を選んで、それを学び、自分で決めるべきだと思います。私があなただったら、Haskellから始めることをお勧めします。Haskellは非常に純粋であり、命令型のコードを書くことができないからです。Erlangと一部のLispも良い選択ですが、それらは他のプログラミングスタイルに混在しています。IMOのScalaとClojureは、最初から非常に複雑です。
-mkalkov
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.