13

Haskellはどのようにして "正規化された不変のデータ構造"の問題を解決しますか?例えば正規化され不変のデータモデル

、のは、元ガールフレンド/ボーイフレンドを表すデータ構造を考えてみましょう:女性は彼女の名前を変更し、彼女は13人であったならば

data Man = Man {name ::String, exes::[Woman]} 

data Woman = Woman {name :: String, exes::[Man]} 

はどうなりますか?そして、13人全員が(更新された)(ハスケルの意味で)これらの「更新」を避けるには、ある種の正規化が必要です。

これは非常に簡単な例ですが、20個のエンティティとその間の任意の関係を持つモデルを想像してください。

複雑な正規化されたデータを不変言語で表現するには、どのような方法が推奨されますか?

たとえば、Scalaソリューションはhere(下記のコードを参照)があり、参照を使用しています。ハスケルで何をすべきか?

class RefTo[V](val target: ModelRO[V], val updated: V => AnyRef) { 
    def apply() = target() 
} 

(スカラ)で上記のような、より一般的な解決策は、Haskellで動作しないか、彼らは必要でない場合、私は、疑問に思いますか?彼らがうまくいかない場合は、どうしてですか?私はハスケルでこれを行うライブラリを検索しようとしましたが、存在しないようです。

つまり、Haskellで正規化されたSQLデータベースをモデリングする場合(たとえば、acid-stateと一緒に使用する場合)、外部キーを記述する一般的な方法はありますか?一般的には、以下のコメントでchepnerが提案したようにIDを手書きでコード化しているわけではありません。

EDIT:換言すればさらに

、データベースは不変であるように(おそらくは持続性のイベントソーシングを使用して)メモリ内のSQL /リレーショナルデータベースを実装(ハスケルまたはスカラのための)ライブラリがあるとほとんどのSQL操作(照会/結合/挿入/削除/など)は実装されており、型保証されていますか?そのようなライブラリがない場合は、どうしてですか?それはかなり良いアイデアのようです。このようなライブラリを作成するにはどうすればよいですか?

EDIT 2:

いくつかの関連リンク:

+6

データを正規化した場合、 'data Man = Man {name :: String、exes :: [WomanID]}'はありません。ここで、 'womanID'はデータ構造のストーリー' Woman'値( 'Map WomanID Woman'のようなもの?' Woman'値の名前を変更した場合、これを参照する 'Man'値には影響しません;' Map'の単一値を更新するだけです。 – chepner

+0

右、問題は、正規化されたデータ構造を作成するための一般的な解決法(IDの取り扱いなどを扱うもの)があるかどうかです。つまり、Haskellersは正規化されたデータを作成するときに何をしますか?彼らはいつもIDを手作業でコードしていますか?この問題のもう少し一般的な解決策はありますか?あなたが提案したのはIDを手でコード化する例ですが、これは自動化できます。決議それらのIDにアクセスしてください。 – jhegedus

+2

@jhegedusそれが立てている質問は、少し広いです - それは本当に状況に依存します。あなたが常に男性と女性を更新している場合は、状態のモナド(州は男性/女性のテーブル/マップ)で計算を実行することができます。もっと一般的なグラフ構造への機能的なアプローチを探しているなら、['fgl'](https://hackage.haskell.org/package/fgl)を見てください。 IDに関して:結び目をつける(https://wiki.haskell.org/Tying_the_Knot)こともある(時には 'Map'を使うこともある)がありますが、一般的にコードIDを渡す必要があるかもしれません。 – Alec

答えて

9

問題は、同じタイプのデータとリレーションシップを格納することです。正規化するには、別々にする必要があります。人は自分の名前を変更した場合、リレーショナルデータベース101

newtype Id a = Id Int -- Type-safe ID. 
data Person = Person { id :: Id Person, name :: String } 
data Ex = Ex { personId :: Id Person, exId :: Id Person } 

は今、一つだけPerson値が影響を受けています。 Exのエントリは、人々の名前を気にしません。

+1

興味深い点!それは実際には多対多の関係です。しかし私が後にしたことは、質問にも言及されているように、「以下のコメントでchepnerによって提案されたようにIDをコード化していません」あなたが示唆したことをするが、すべての定型文を取り除き、クエリ、結合などのサポートを追加するライブラリのようなもの。基本的にSQLデータベースですが、SQLをクエリ言語として使用する代わりに、Haskellを使用してSQLで記述できるものを記述します。型は安全で不変です。 – jhegedus

+0

@jhegedusここに事があります。外部キーを抽象化することはできません。それはあなたのドメインセマンティクスの一部です。つまり、「あなたは関係の人を何にするのですか?」という質問に答えます。あなたのためにそれを決定するライブラリはありません。 – Yawar

+0

したがって、基本的に「Ex」は明示的に指定する必要があるSQLデータベーステーブルに対応します。私はそれを得るが、多分SQLはHaskellに置き換えることができ、完全な型安全で不変である。か否か ?私はなぜそれが行われていないのだろうか? (データベースへのバインディングではなく、実際のメモリ内のデータベース、Haskellで書かれています)。私はこれは、友人がScalaで(成功した)アプリケーションを書いているので、正確にやっているからです。なぜなら、1)データの重複(メモリデータベース)、2)型の安全性、3)ScalaはSQLよりも表現力が高いからです。だからScalaでそれを行う価値があるなら、なぜHaskellのlibはありません。それのために存在する? – jhegedus

0

プロジェクトM63は、私が探していたものにかなりcloseが来ます。ハスケルに書かれています。

ガボット・ゴンザレスの投稿「A very general API for relational joins」に、より軽量なハスケル・ソリューションが概説されています。

+0

質問したモデルにProject M63を具体的に適用する方法の例を挙げることができますか?また、「閉じる」というテキストのリンクは、個人のGmailの受信トレイにあるメッセージのようです。 Gabriel Gonzalezの参加テクニックはかなり涼しいですが、それでもID管理を抽象化していません – Yawar

+0

ありがとう、私はリンクを修正しました。 – jhegedus

+0

M36の使い方はわかりませんが、私が探していたようです。変更不能なリレーショナルデータベース。 Scalaに相当するものは存在しないようです(少なくとも公開されていないもの)。それとも、私はそれについて知りませんか? Scala用のM36のようなものがあるかどうかを知ることは面白いでしょう。 – jhegedus

関連する問題