IDと変更可能な永続状態を持つエンティティは、関数型プログラミング言語でどのようにモデル化されますか?


8

この質問(ピートによって書かれた)への回答では、OOPとFPに関するいくつかの考慮事項があります。特に、FP言語は、同一性と変更可能な状態を持つ(永続的な)オブジェクトのモデリングにはあまり適していないことが推奨されます。

これが本当かどうか、つまり、関数型プログラミング言語でオブジェクトをモデル化する方法を考えていました。Haskellの基本的な知識から、モナドはなんらかの方法で使用できると思いましたが、このトピックについては明確な答えを出すのに十分な知識がありません。

それでは、アイデンティティと変更可能な永続状態を持つエンティティは通常、関数型言語でどのようにモデル化されますか?

ここに、私が考えていることを明確にするための詳細をいくつか示します。(1)データベーステーブルからJavaオブジェクトにレコードを読み取る、(2)さまざまな方法でオブジェクトを変更する、(3)変更されたオブジェクトをデータベースに保存できる、典型的なJavaアプリケーションを取り上げます。

これはどのようにしてHaskellに実装されますか?最初にレコードをレコード値(データ定義で定義)に読み込み、この初期値に関数を適用してさまざまな変換を実行し(各中間値は元のレコードの新しい変更されたコピーです)、最終的なレコード値を書き込みますデータベースに。

これで全部ですか?各時点でレコードの1つのコピーのみが有効/アクセス可能であることをどのように確認できますか?同時にアクセスできるように、同じオブジェクトの異なるスナップショットを表す異なる不変の値を使用したくない場合があります。


言語に依存します。Clojureの作者であるRich Hickeyは、データ構造(リスト、辞書、セットなど)を使用してデータを表すことをお勧めします。私はそのアイデアを完全に売り切っているわけではありません。インデックスやニーモニックではなく名前でフィールドを逆参照したいのですが、コンパイラにチェックアップしてもらいました。F#には、クラスのような構造があります。msdn.microsoft.com/en-us/library/dd233233.aspx JavaやC#を使用していても、まったく新しいオブジェクトを作成することで「変更」できる不変オブジェクトを作成できます。
ジョブ

1
@gnat:タイトルを編集していただきありがとうございますオブジェクトは間違いなく最も適切な用語ではありませんでした。
ジョルジオ

回答:


7

Haskellのような純粋な言語で状態変更を行う通常の方法は、古い状態を取り、変更されたバージョンを返す関数としてそれらをモデル化することです。複雑なオブジェクトの場合でも、Haskellの遅延評価戦略により、これは効率的です。構文的に新しいオブジェクトを作成している場合でも、オブジェクト全体がコピーされるわけではありません。各フィールドは、必要なときにのみ評価されます。

ローカル状態の変更がいくつかある場合、モナドが入る場所が不便になる可能性があります。モナドパラダイムを使用して、状態とその変更をカプセル化できます。教科書の例は、State標準のHaskellインストールに付属するモナドです。ただし、モナドは特別なものではないことに注意してください。これは、2つのメソッド(>>=およびreturn)を公​​開するデータ型であり、いくつかの期待に応えます(「モナドの法則」)。内部的には、Stateモナドはまったく同じです。古い状態を取り、変更された状態を返します。構文のみが優れています。


2
怠惰は間違った言葉だと思います。Haskellは状態の変更されていないサブコンポーネントを共有できるため、効率的です。これは、型レベルで可変性を提供する任意の言語で発生する可能性があります。
Daniel Gratzer 2013年

@jozefg-それは本当かもしれないが、Haskellでは少なくともその実装は本質的に言語の怠惰に結びついている。構造体の値全体が必要な場合にのみ計算され、更新を表すサンクのチェーンがその時点で、要求されたメンバーの最新の値が何であるかを決定するために必要な範囲でのみ評価されるため、単純に機能します。純粋な厳格な言語では、効率的にするために、プリミティブとしてレコード更新操作が必要です。Haskellはその怠惰のためではありません。
ジュール

2

私は関数型言語の開発者ではないので、もし私が間違っている場合は私を炎上させてください、しかしもし正しければ、それは興味深い類推かもしれません。

かつて、Excelは本質的に関数型言語であると言われました。私はVBAなどについて話しているのではなく、シートで何が起こるかについて話している。

したがって、表、個々のセル、または名前付き範囲などの入力があり、一連の操作を通じて結果が1つまたは多くの結果になります。1つの入力を変更すると、すぐに流れます。

そのアナロジーは水を保持していますか?


1
権威からの引数、あなたは正しいです;)
phant0m

1
私はそのようなExcelを使用する方がデータフロープログラミングに似ていると思いますが、Excelが適合する可能性には多少の余裕があります。個人的には、そもそもそれを言語と呼ぶかどうかは定かではありません...
イズカタ

1
あなたはそこにポイントを持っています。しかし、それでもExcelはその点で機能しています。PS:プレゼンテーションをご覧になることをお勧めします。とても興味深いと思います。
phant0m 2012

@Izkata Excelは、データフロープログラミングの特別なケースを表します。リアクティブプログラミング
itsbruce 2015年

2

純粋な関数型言語のステートレスな特性について話していると思います。

初期状態を入力として受け取り、最終状態を出力として返します。状態の概念を持つ言語で行うことと根本的に異なることはありませんが、それについてより明確であり、面倒で効率が悪い場合があります(*)。

オブジェクトを参照するすべての場所を変更する必要はないことに注意してください。トークンを保持している場合があり、トークンを現在の状態にマップするデータ構造を変更するだけです。それまでに、ステートレス言語を使用してステートフルシステムを実装し、ステートフル言語の問題を取り戻します。


(*)たとえば、O(1)で連続した整数によってインデックス付け可能なデータ構造の変更されたコピーをO(1)で返すことができるデータ構造を探しましたが見つかりませんでした。


+1。はい、私はオブジェクトのようなステートフルエンティティ(アイデンティティと後続の状態の履歴を持つ)をステートレス言語でモデル化することについて言及していました。Javaのような言語であなたの例((*)でマークされている)の対応物は何ですか?配列?オブジェクトの配列?
Giorgio

@ジョルジオ、はい。O(log n)でこれを行う方法は知っていますが、O(1)ではできません-そして定数係数もヒットします。ステートフル言語で元に戻すを実装する方法として、純粋な関数型言語用に設計されたデータ構造を使用していることに注意してください。
AProgrammer 2012

ちなみに、トライは技術的に O(1)であり、そのようなことを論じるときによく使用される同じ単純化の仮定の下で、存在する要素の数に時間の複雑さは依存しない挿入/削除操作を伴う可変サイズのコレクションです。ただし、これらは実際には可変配列とは比較できません。
CAマッキャン2012

通常の連想リストで[(Int, v)]は、新しい値を単にコンストレイントするだけで、任意のインデックスの値を一定の時間で置き換えることができます。欠点:古い値は依然としてRAMを使用しており、検索は線形です。
singpolyma 2012年

1

つまり、エンティティの各状態はそれ自体のエンティティです。したがって、従来の「順序付け」ビジネスロジックには、OrderエンティティとOrderVersionエンティティがあります。どちらも不変です。ラインアイテムを追加するロジックは、古いバージョンと新しいバージョンをOrderLineItemVersion入力として取り、新しいOrderVersionエンティティを返します。

いくつかのことは簡単になりますが(特に「元に戻す」機能)、いくつかのことはより困難です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.