「属性」と「関係」

OOP の属性は所有関係であり主従関係にあり, 関係を表すものとしては特殊. そうではなく一般の主従ではない関係を表すことはできないか? という疑問が発端の会話. ちょっと脱線話も入れました.
11
pokarim @pokarim

@cocoatomo 関係'の合成は、lambda left,right:lambda xs:[z for ys in left(xs) for zs in right(ys) for z in zs] です。構文は、父.上司.年齢で、年齢(上司(父(xs)))な意味です。

2010-11-23 17:22:29
pokarim @pokarim

@cocoatomo where句的なものとして関係'の関数filterを使います。その前に比較演算子を用意します。比較演算子の型は([a]->[b])->([a]->[b])->[a]->[Bool]な感じです。

2010-11-23 17:37:31
pokarim @pokarim

@cocoatomo [会社員]->[Int]な関係'として体重と身長があった場合、体重<身長で、[会社員]->[Bool]に、filter(体重<身長)で[会社員]->[会社員]になります。

2010-11-23 17:41:52
pokarim @pokarim

またちょっとばかし用事。

2010-11-23 17:44:26
pokarim @pokarim

@cocoatomo あとは関係'の水平合成的なものとして、(left, right) で、lambda xs:(left(xs), right(xs))を表すことにします。とりあえずselectに対応するクエリーに関してはこれらの道具で同等の事ができます。

2010-11-23 21:08:09
pokarim @pokarim

@cocoatomo 関係性の変化、RDBにおけるinsert,updateに対応するものも考えてあります。

2010-11-23 21:14:59
pokarim @pokarim

@cocoatomo 基底となる関係'は、内部的には入力値と出力値のペアの多重集合で表されます。ある関係'を変更するには、入力値と、出力値の集合のペアを渡せばいい事になります。(入力値, {出力値1,出力値2,..})これがupdateに相当します。構文はあとにまわします。

2010-11-23 21:26:48
pokarim @pokarim

@cocoatomo 関係'には、合成などの演算により他の関係'から導出された関係'と、そうでない基底となる関係'があります。とりあえずsub関係'とbase関係'と呼びます。直接変更を加えるのはbase関係'のみです。sub関係'は依存する関係'の変化に応じて勝手に変化します。

2010-11-23 21:19:55
pokarim @pokarim

@cocoatomo 次はinsertです。文字列や数値でない、会社員オブジェクトのようなオブジェクトは、IDの集合になります。ID型のオブジェクトに対しては、新たなIDをひとつ生成する単純な操作を用意します。これがinsertに相当します。

2010-11-23 21:29:59
pokarim @pokarim

@cocoatomo 次はinsertです。文字列や数値でない、会社員オブジェクトのようなオブジェクトは、IDの集合になります。ID型のオブジェクトに対しては、新たなIDをひとつ生成する単純な操作を用意します。これがinsertに相当します。

2010-11-23 21:29:59
pokarim @pokarim

@cocoatomo insertの続きですが、文字列型や数値型のオブジェクトに対してのinsertは必要ないので考えません。値型のオブジェクトは外見上は値の集合ですが内部に一覧データは持たず、そのオブジェクトを指す関係'から要素が決定されます。

2010-11-23 21:33:32
pokarim @pokarim

@cocoatomo 最低限のinsert、update相当の操作の枠組みだけ示しましたが、実際には各関係'を別々に更新するのは煩雑なので、まとめて更新する仕組みを別途用意します。その前にさっきのタプル型の関係'を拡張して名前付きタプルにします。

2010-11-23 21:38:51
pokarim @pokarim

@cocoatomo 名前付きタプルの表記にはJSONの連想配列を借ります。あくまで名前付きタプルなので、キーは全て文字列、値の型はキーごとに違うものになります。

2010-11-23 21:42:26
pokarim @pokarim

@cocoatomo 関係'を並列合成して、出力値の型を名前付きタプル型にする操作としても、同じJSONの構文を使います。ちょっとややこしいので例を使います。会社員オブジェクトと上司:会社員->会社員、社員名:会社員->Str、体重:会社員->Intの3つの関係'を考えます。

2010-11-23 21:50:41
pokarim @pokarim

@cocoatomo {joshi_mei:上司.社員名,w:体重}の表記で、社員->{joshi_mei:社員,w:Int}型の関係'を表します。具体的な出力値としては{joshi_mei:["hoge"],w:[60]}といったものになります。

2010-11-23 21:58:26
pokarim @pokarim

@cocoatomo 出力値はつねに多値なので、完全な出力値としては、[{joshi_mei:["hoge"],w:[60]}, {joshi_mei:["fuga"],w:[]}]といったものになります。

2010-11-23 22:03:39
pokarim @pokarim

@cocoatomo つぎにオブジェクトから、自分自身を返す恒等射的な関係'を得る関数としてIDを用意します。ID(会社員)で会社員オブジェクトにたいするlambda xs:xsな関係'を表します。ID(hoge)のhogeの部分は文脈から決まる場合省略可とします。

2010-11-23 22:06:39
pokarim @pokarim

@cocoatomo ID型の値は、識別できればなんでもいいですが、RDBのシーケンスのように自動で連番の整数値が振られることにします。他のInt値と区別するため、001,002などと表記します。

2010-11-23 22:13:22
pokarim @pokarim

@cocoatomo 社員オブジェクトは、Identity型のオブジェクトですが、これと恒等射がややこしいので、恒等射をとる関数はid、オブジェクトの型としてはID型と分けることにします。

2010-11-23 22:10:59
pokarim @pokarim

@cocoatomo 名前付きタプルにidを組み合わせた{id:id,name:社員名,w:体重}という関係'からは、[{id:[001], name:["hoge"],w:[66]}]といった値が得られます。この形の値を逆に関係'に突っ込んでやれば複数の関係'が更新できます。

2010-11-23 22:21:10
pokarim @pokarim

@cocoatomo 便宜的なルールになってきますが、[{id:[null], name:["hoge"],w:[66]}]を突っ込むことで、会社員オブジェクトの要素をひとつinsertして社員名や体重の関係'も同時に更新することにします。

2010-11-23 22:27:56
pokarim @pokarim

@cocoatomo 他から導出された関係'に対しては直接変更を加えないと書きましたが、逆向きをとる演算invertだけは直接の変更を許します。invertは内部表現のペアの多重集合のペアをswapした関係を得る事に相当します。

2010-11-23 22:32:15
pokarim @pokarim

@cocoatomo 例えば、部下 = invert(上司)としておけば、部下に対する変更操作が自明なルールで上司への変更操作に変換されることにします。

2010-11-23 22:33:45
pokarim @pokarim

@cocoatomo {id:id,buka:部下,name:社員名}といった形の関係'を作れば、任意の深さのツリーの値が得られます。また任意の深さのツリーで関係'をinsert,updateできます。とりあえず上司の関係'がループしていないことが前提です。

2010-11-23 22:37:12
pokarim @pokarim

@cocoatomo 都合のためきょうのところは切り上げて寝ます。今日はありがとうございました。

2010-11-23 22:40:15