130

私はしばらくの間 Web 開発者であり、最近関数型プログラミングの学習を開始しました。他の人たちと同じように、私はこれらの概念の多くを専門的な仕事に適用するのにかなりの苦労をしました。私にとって、これの主な理由は、ステートレスであり続けるという FP の目標と、私が行ったほとんどの Web 開発作業が非常にデータ中心のデータベースに大きく結びついているという事実との間に矛盾があるように見えることです。

OOP 側の開発者としての生産性を大幅に向上させたのは、.Net 用の MyGeneration d00dads、perl 用の Class::DBI、Ruby 用の ActiveRecord などのオブジェクト リレーショナル マッパーを発見したことです。挿入ステートメントと選択ステートメントを 1 日中書くことから解放され、データをオブジェクトとして簡単に操作することに集中できます。もちろん、SQL クエリの機能が必要な場合は引き続き SQL クエリを作成できましたが、それ以外の場合は、バックグラウンドで適切に抽象化されていました。

さて、関数型プログラミングに目を向けると、Links のような多くの FP Web フレームワークでは、この例のように定型的な SQL コードをたくさん書く必要があるようです。Weblocks は少し優れているように見えますが、データを操作するためにある種の OOP モデルを使用しているようで、この例のようにデータベース内のテーブルごとに手動でコードを記述する必要があります。コード生成を使用してこれらのマッピング関数を記述していると思いますが、それは明らかに Lisp らしくないようです。

(私は Webblock や Links をあまり詳しく見ていないことに注意してください。それらがどのように使用されているかを誤解しているだけかもしれません)。

問題は、Web アプリケーションのデータベース アクセス部分 (かなり大きいと思います)、または SQL データベースとのインターフェイスを必要とするその他の開発では、次のパスのいずれかを強制されるように思われることです。

  1. 関数型プログラミングを使用しない
  2. 多くの SQL または SQL に似たコードを手動で記述することを含む煩わしい抽象化されていない方法でデータにアクセスするリンク
  3. 関数型言語を疑似 OOP パラダイムに強制することで、真の関数型プログラミングの優雅さと安定性の一部を取り除きます。

明らかに、これらのオプションはどれも理想的とは思えません。これらの問題を回避する方法を見つけましたか? ここに本当に問題がありますか?

注: 私は個人的に FP の面で LISP に最も精通しているので、例を挙げて複数の FP 言語を知りたい場合は、おそらく lisp が最適な言語になるでしょう。

PS: Web 開発の他の側面に固有の問題については、この質問を参照してください。

4

10 に答える 10

83

データベース担当者の観点からすると、フロントエンド開発者は、オブジェクト指向または機能的ではなく、リレーショナルで使用するデータベースを使用する最も効果的な方法を検討するのではなく、データベースをモデルに適合させる方法を見つけるのに苦労していることがわかります。集合論。私はこれが一般的にパフォーマンスの悪いコードをもたらすのを見てきました。さらに、パフォーマンスの調整が難しいコードを作成します。

データベースアクセスを検討する場合、主に3つの考慮事項があります。データの整合性(すべてのビジネスルールをユーザーインターフェイスではなくデータベースレベルで適用する必要がある理由)、パフォーマンス、およびセキュリティです。SQLは、最初の2つの考慮事項をどのフロントエンド言語よりも効果的に管理するように作成されています。それはそれを行うために特別に設計されているからです。データベースのタスクは、ユーザーインターフェイスのタスクとは大きく異なります。タスクの管理に最も効果的なコードの種類が概念的に異なるのは不思議ではありませんか?

また、データベースには、企業の存続に不可欠な情報が含まれています。存続が危機に瀕しているときに、企業が新しい方法を実験することをいとわないのは不思議ではありません。多くの企業は、既存のデータベースの新しいバージョンにアップグレードすることすら望んでいません。したがって、データベース設計には本質的な保守主義があります。そしてそれは故意にそのようです。

T-SQLを記述したり、データベース設計の概念を使用してユーザーインターフェイスを作成したりすることはしません。なぜ、インターフェイス言語と設計の概念を使用してデータベースにアクセスしようとするのでしょうか。SQLは派手ではない(または新しい)とは思わないのでしょうか?それともあなたはそれを快適に感じませんか?何かがあなたが最も快適に感じるモデルに合わないからといって、それが悪いか間違っているという意味ではありません。それは、それが異なっており、おそらく正当な理由で異なっていることを意味します。別のタスクに別のツールを使用します。

于 2008-12-01T19:22:28.380 に答える
46

まず第一に、CLOS (Common Lisp Object System) が「疑似 OO」であるとは言いません。ファーストクラスOOです。

第二に、ニーズに合ったパラダイムを使用する必要があると思います。

関数はデータの流れであり、状態は実際には必要ありませんが、ステートレスにデータを格納することはできません。

いくつかのニーズが混在している場合は、パラダイムを混ぜ合わせてください。ツールボックスの右下隅のみを使用するように制限しないでください。

于 2008-12-01T11:33:00.763 に答える
31

Ben Moseley と Peter Marks による論文「Out of the Tar Pit」を参照してください。「Out of the Tar Pit」(2006 年 2 月 6 日)から入手できます。

これは、Functional-Relational Programming と呼ばれるプログラミング パラダイム/システムを詳述するモダン クラシックです。データベースとは直接関係ありませんが、システムの機能コアから外界 (データベースなど) とのやり取りを分離する方法について説明します。

また、アプリケーションの内部状態がリレーショナル代数を使用して定義および変更されるシステムを実装する方法についても説明します。これは明らかにリレーショナル データベースに関連しています。

このホワイト ペーパーでは、データベースと関数型プログラミングを統合する方法について正確な回答を提供することはできませんが、問題を最小限に抑えるシステムを設計するのに役立ちます。

于 2012-05-08T10:01:00.597 に答える
26
  1. 関数型言語には、ステートレスを維持するという目標はなく、状態の管理を明示的にするという目標があります。たとえば、Haskellでは、Stateモナドを「通常の」状態の中心と見なすことができ、IOモナドはプログラムの外部に存在する必要がある状態の表現と見なすことができます。これらのモナドはどちらも、(a)ステートフルアクションを明示的に表現し、(b)参照透過性ツールを使用してそれらを構成することにより、ステートフルアクションを構築することができます。

  2. 多数のORMを参照します。これらのORMは、その名前ごとに、データベースをオブジェクトのセットとして抽象化します。確かに、これはリレーショナルデータベースの情報が表すものではありません!その名前のとおり、リレーショナルデータを表します。SQLは、リレーショナルデータセットの関係を処理するための代数(言語)であり、実際にはそれ自体が非常に「機能的」です。これは、(a)ORMがデータベース情報をマップする唯一の方法ではないこと、(b)SQLは実際には一部のデータベース設計にとって非常に優れた言語であり、(c)関数型言語には関係代数があることが多いことを考慮するために取り上げます。 SQLの力を慣用的な(そしてHaskellの場合はタイプチェックされた)方法で公開するマッピング。

ほとんどのLispは貧乏人の関数型言語だと思います。現代の機能慣行に従って完全に使用することができますが、それらを必要としないため、コミュニティがそれらを使用する可能性は低くなります。これにより、非常に便利な方法が混在することになりますが、純粋な機能インターフェイスがデータベースを有意義に使用する方法が確実にわかりにくくなります。

于 2012-05-08T13:32:58.623 に答える
15

データベースが情報を破壊しない場合は、データベース全体の関数を値として操作することにより、「純粋な機能」プログラミング値と一致する機能的な方法で情報を操作できます。

時間 T でデータベースが「Bob likes Suzie」と述べており、データベースと liker を受け入れる関数 likes を持っていた場合、時間 T でデータベースを回復できる限り、データベースを含む純粋な関数型プログラムを使用できます。 . 例えば

# Start: Time T
likes(db, "Bob")
=> "Suzie"
# Change who bob likes
...
likes(db "Bob")
=> "Alice"
# Recover the database from T
db = getDb(T)
likes(db, "Bob")
=> "Suzie"

これを行うには、使用する可能性のある情報を捨てることはできません (つまり、実際には、情報を捨てることができないということです)。そのため、必要なストレージは単調に増加します。しかし、データベースを一連の離散値として扱い始めることができます。この場合、後続の値はトランザクションを通じて前の値に関連付けられます。

たとえば、これはDatomicの背後にある主要なアイデアです。

于 2012-05-08T12:20:17.267 に答える
15

fp 言語のステートレスな性質がデータベースへの接続に問題があるとは思いません。Lisp は非純粋な関数型プログラミング言語であるため、状態の処理に問題はありません。また、Haskell のような純粋な関数型プログラミング言語には、データベースの使用に適用できる入力と出力を処理する方法があります。

あなたの質問から、あなたの主な問題は、データベースから返されたレコードベースのデータを抽象化して、多くの SQL を書かなくても Lisp-y (lisp-ish?) になる良い方法を見つけることにあるようです。コード。これは、言語パラダイムの問題というよりも、ツール/ライブラリの問題のようです。純粋な FP を実行したい場合、lisp は適切な言語ではない可能性があります。Common Lisp は、純粋な fp よりも、oo、fp、およびその他のパラダイムからの優れたアイデアを統合することに重点を置いているようです。純粋な FP ルートに進みたい場合は、Erlang または Haskell を使用する必要があるかもしれません。

Lisp の 'pseudo-oo' アイデアにもメリットがあると思います。あなたはそれらを試してみたいかもしれません。それらがデータを操作したい方法に合わない場合は、Webblock の上にレイヤーを作成して、データを希望どおりに操作できるようにすることができます。これは、自分ですべてを書くよりも簡単かもしれません。

免責事項: 私は Lisp の専門家ではありません。私は主にプログラミング言語に興味があり、Lisp/CLOS、Scheme、Erlang、Python、そして少しの Ruby で遊んでいます。日常のプログラミング生活では、いまだに C# を使わざるを得ません。

于 2008-12-01T10:44:54.103 に答える
12

全くない。「機能データベース」として知られるデータベースのジャンルがあり、Mnesiaはおそらく最もアクセスしやすい例です。基本的な原則は、関数型プログラミングは宣言型であるため、最適化できるということです。永続的なコレクションに対してリスト内包表記を使用して結合を実装すると、クエリ オプティマイザが自動的にディスク アクセスの実装方法を見つけ出すことができます。

Mnesia はErlangで書かれており、そのプラットフォームで利用可能なWeb フレームワーク ( Erlyweb )が少なくとも 1 つあります。Erlang は本質的に非シェアード スレッド モデルと並行しているため、ある意味ではスケーラブルなアーキテクチャに適しています。

于 2008-12-01T09:33:41.657 に答える
6

データベースは、ステートレス API で状態を追跡するのに最適な方法です。REST にサブスクライブする場合、目標は、状態情報を透過的に追跡するデータストア (またはその他のバックエンド) と対話するステートレス コードを記述して、クライアントがそうする必要がないようにすることです。

データベース レコードをオブジェクトとしてインポートし、それを変更するオブジェクト リレーショナル マッパーの考え方は、オブジェクト指向プログラミングと同様に、関数型プログラミングにも適用可能であり、有用です。1 つの注意点として、関数型プログラミングはオブジェクトをその場で変更しませんが、データベース API を使用するとレコードをその場で変更できます。クライアントの制御フローは次のようになります。

  • レコードをオブジェクトとしてインポートします (データベース API はこの時点でレコードをロックできます)。
  • 好きなようにオブジェクトとその内容に基づいてブランチを読み取り、
  • 必要な変更を加えて新しいオブジェクトをパッケージ化します。
  • データベースのレコードを更新する適切な API 呼び出しに新しいオブジェクトを渡します。

データベースは、変更内容でレコードを更新します。純粋な関数型プログラミングは、プログラムのスコープ内で変数を再割り当てすることを許可しない場合がありますが、データベース API では引き続きインプレース更新を許可できます。

于 2015-08-28T23:01:25.147 に答える
5

私はHaskellに最も慣れています。最も有名な Haskell Web フレームワーク (Rails や Django に相当) は Yesod と呼ばれます。かなりクールでタイプセーフなマルチバックエンド ORM を備えているようです。彼らの本の持続性の章を見てください。

于 2012-05-08T09:21:05.060 に答える
1

データベースと関数型プログラミングは融合できます。

例えば:

Clojure は、リレーショナル データベース理論に基づく関数型プログラミング言語です。

               Clojure -> DBMS, Super Foxpro
                   STM -> Transaction,MVCC
Persistent Collections -> db, table, col
              hash-map -> indexed data
                 Watch -> trigger, log
                  Spec -> constraint
              Core API -> SQL, Built-in function
              function -> Stored Procedure
             Meta Data -> System Table

注: 最新の spec2 では、spec は RMDB に似ています。参照: spec-alpha2 wiki: Schema-and-select

私が提唱するのは、ハッシュマップの上にリレーショナルデータモデルを構築して、NoSQL と RMDB の利点の組み合わせを実現することです。これは実際には posgtresql の逆の実装です。

アヒルのタイピング: アヒルのように見え、アヒルのように鳴く場合、それはアヒルに違いありません。

clojure のデータ モデルが RMDB のようであり、clojure の機能が RMDB のようであり、clojure のデータ操作が RMDB のようである場合、clojure は RMDB でなければなりません。

Clojure は、リレーショナル データベース理論に基づく関数型プログラミング言語です。

すべてRMDBです

ハッシュマップ (NoSQL) に基づくリレーショナル データ モデルとプログラミングの実装

于 2019-05-11T13:58:04.467 に答える