<2012年2月1日 改訂>
R3は変動,変化する実体を記述することをその目的の一つであるとしてきた.変動する実体とは何か.実体とよぶものは実世界の要素である.しかし,前稿で,実世界自体はどんな能知に対してもその所知の所与面として不変であるとした.能知は参照基準点(point of reference)であるとみなせ,その因子として時間を考えることが出来る,とも述べた.とすると,「変動する実体」という言い回しは一見,自己矛盾をはらむことになる.より正確には,実体を所知の要素とし,その所知の所識面が変動する,つまり能知(参照基準点)のパラメータを持つ,ということである.参照基準点が時間(あるいは他の要因)が変わることによって変動するために,実体の所識面(つまり実体の認識結果)が変動する(ように見える)ということである.実体の所与面は不変であり,その覚知が実体のイデアたるゆえんとなる.しかしこの考え方も正確ではない.
前稿で,能知,あるいは参照基準点には,「だれが,いつ,どこで,なぜ,どのように」の要因を持つと述べた.「だれが」は,認識者,『いつ』は時間,「どこで」は認識者のいる場所,「なぜ」は,認識者の動機と関心,『どのように』は観察手段などである.「これに「何を」を追加すれば,5W4Hになるが,『何を』は所知であるから,5W4Hはノエシスの要因をいみじくも表している.
参照基準点のどれかが変わればそれによって対象とする所知の所識が変わる.つまり認識結果が変わる.それをもって『実体は変動する』といっているのである.しかし,4W1Hについてすべて議論するのは複雑なので,以下では,主として時変動を考えることにする.
普通の大人ならば,夕日は沈んで一旦見えなくなるが翌日昇る朝日はそれと同じ太陽だ,と考える,幼児も,母親がいないいないばーをして一旦見えなくなっても同じ母親を見続けていると認識する(学習する?).そのとき,実世界の実体(所与)としての太陽と母親は不変であり,時間と共に変化するのは認識者(能知)である自分のほうで,その自分からみると太陽あるいは母親が変化するように見える(所識)のだ,と考えていることになる.つまり誰しもが(ほとんど無意識のうちに)思考のコペルニクス的転回を行っている.しかし,はたして所与は真に不変なのだろうか.このように考えるのは,所与(イデア)のそれこそ物象化である.イデア(あるいは空)は語れないものである.それが「不変」,あるいは反対に「可変」だというのは,語っていることになる.実は,所与である実世界における不変性,唯一性と呼んでいるものは,認識行為が定めるものであってそれ以上のものではない.すなわち,朝日と夕日が同じ太陽だと考えるか別のものと考えるのかは能知によるものであって,絶対的なものではない(前稿のノエマ射 ξ(r) は認識者 r に依存する).しかし,時間 t の自分を st として, st と st' どちらも同一の能知の要素とする,つまり 時間の異なる自分を共同主観性を持つものとすれば(自己分裂しない限りそうであろう),この二人?の認識は一致して,太陽が同一とするかどうかの見解は同じになる.同一と考えるとき,認識のコペルニクス的転回をおこしていて,所与としての太陽が不変であると認識することになる.一般に,複数の要素からなる能知による認識では,個人,時間,空間,まして,動機や観察手段などを超えて(つまり,共同主観性を持つことにより),実世界での実体の不変性について一致する.実際,対象実世界の不変性を求める科学は,自ら定めた検証作業により,共同主観を拡大し,堅固にする営為であるといえる.なぜなら,不変性の認識こそすべての推論の基礎となるからである.
こうして,共同主観によって不変であると認識される実世界の一要素が『実体』とよぶものである.R3ではそれをentityと呼び,その識別子としてentity_idまたはrun_idを与える.
さて,では実体の変動とはなにか.「実体」そのもの,という不変なものが想定されて,そのうえにたってはじめて議論することが出来る.
まず,すでの認識されている実体の変化は,その状態の変化であると見なせる.状態は実体の属性であるから,属性射が変動すると考えるのである.
次に,実体が「生じる,誕生する」とはどういうことか.逆に「消える,消滅する」とは?実体は所与側での不変性が認識されているという前提があるから,その所識側に現れるか,あるいは,消えるか,ということに相当すると考える.つまり,認識されるようになったか,認識されなくなったか,ということである.
圏論ではこのような射の変更を作用actionと呼ぶ.その詳細な議論については後述する.
以下,McTaggartの時間の非実在性について.
J. M. E. McTaggartはおよそ100年前に時間の非実在性について論じた(The Unreality of Time).以降,現在でもそれについてさまざまな議論が続いている.McTaggartは「ある時間 T に起きる事象は(時間の推移と共に)未来であり,現在であり,かつ過去である.同一物に相反する述語が付けられるのは矛盾する.したがって時間は非実在である」というような論法を立てている.上述の立場に立ってこの論法を見直してみよう.時間 T というのは,たとえば,「大地震が起きたとき」であり,それは(日本時間で)2011.3.11 14:46のように識別子が付けられ,それ自体は不変である.つまり,認識対象となる「時間」は,能知によらず共同主観性によって不変であるとされる.それに対し,(認識対象としての)「現在」をNowと表したとき,Now は能知の因子である時間 t(これは先の時間とは違うことに注意)に依存するから,Now(t)と表すことにする.T における事象が「未来である」とは T > Now(t) ,「現在である」とは T = Now(t) ,「過去である」とは T < Now(t) であるから,これらは決して相反する述語(形容)ではない.したがってなんら矛盾を起こさないではないか,というのが常識的な見方であろう.
McTaggartはこの論法について,時間の説明に時間を使っているから悪循環論法である,といって拒否する.しかし,ここで,T は認識対象としての「時間」であり,t は能知圏で対象とする「時間」であって,両者は別物であるため,この論駁は成り立たない.しかし,では能知の t という「時間」とは何なのか,これはカントが先験的(a priori)カテゴリとした認識に先立つ概念装置であり,実際,われわれの立場から見ても認識対象とはされない.つまり所知の所与側の世界に入らない.その意味で,時間 t は確かに実在とは認められないという意味で「非実在」である.McTaggart自身,論文のなかでそのような示唆を与えている.
McTaggartは時間の特性についても一つ重要な論点をあげている.未来(の出来事)はいつかは現在になり,過去になるが,過去はずっと過去であって,その意味で未来とも現在とも異なる.その区別を与えるためには順序の向きが与えられなければならない.時間の比較として大小比較(”>")だけでは三者の順序の向き(昇順か降順か)が与えらていない.したがってこの常識的論法では時間の特性を示すものとして不十分だ,というのである.これは認知者のもつ記憶機能に関係する.認知者を情報システムとすれば,記録機能である.認識された事象(将来ならば,その予測または計画)をその事象の起きた順にリストにする(記録する)ことにより,この時間の向きの特性が与えられる.これがMcTaggartのいうC系列である.ちなみに,「未来,現在,過去」の区分系列をA系列,昇順か降順かが与えられない相互比較だけの系列をB系列とよんでいて,A系列とBないしC系列とが組み合わされてはじめて時間の特性が表現されるが,A系列が矛盾を含むので時間は非実在であるというのが(拙見による)McTaggart論法である.しかし,本当に非実在とするべきは能知の時間であって,観測対象としての事象にともなう時間ではないことは上述の通り.
同じ能知の因子である「空間(場所)」についても同様の議論が出来る.McTaggart流に言えば,「ある事象が起きる場所 P が(能知が移動することによって)前にあり,あるいはここにあり,あるいは後ろにある,というように,同一物に相反する述語が付けられるから,場所は非実在である」となってしまうが,時間についてと同様の議論になる.ここで真に非実在とするべきは,観測対象としての場所ではなく,能知の場所(認識者がいる場所)である.これもカントがアプリオリなカテゴリとしたものである.
認識対象としての事象に伴う時間や場所が非実在であるとしたら,物理学はもちろん,すべての科学が成り立たないことになる.McTaggartもそこまで言うつもりはなかっただろう.
R3では,事象の時間(一般には巾があるduration)と場所をその属性としてしているが,これはもちろん認識対象としての時間と場所である.またその事象を事実とすれば,事実グラフの属性値としてデータベースに記録される.時間に関してみれば,それはC系列を表すことになる.
多くの情報システムでは,事実が変化するとそれをそれまでの記録に上書きして記録してしまう.たとえばメーリングリスト.部署のメーリングリストを作って使用する組織が多いと思うが,人事異動などでそのメンバーが変わるとリストの記録をそれに合わせて変えてしまい,それまでのものは残さない.ウェブのホームページの変更もそういうものが圧倒的に多いのではないだろうか(実は,このブログも同じ).これは,A系列のなかの現在のみで生きるいわば刹那主義である.こうして日々刻々,膨大な情報が「現在」とともに流れ去っていく.R3は現代情報システムのそういう刹那主義に警鐘をならすものである.
Running Ruby on Rails
2012年1月30日月曜日
2012年1月18日水曜日
圏論による実世界のモデル化とOOP
<2012/01/23 大幅に改訂>
情報システムのモデル部は対象とする実世界の記述である.記述は認識の上に立つから,どのようにすれば実世界を正しく認識することが出来るのか,それがまず問われる.ならば,「認識行為」とはどのようなものであると考えるのか.その問いに対し,哲学の一分野として認識論があり,長い歴史と進化がある.では,OOPはどのような認識観に立つのだろうか.あるいは,どのような認識観で説明できるのだろうか.残念ながらそのような問いに答える論述を知らない.そこで,荒いながらも拙論を述べる.なお哲学全般については,主に,熊野純彦著:西洋哲学史(岩波新書2006年)と,廣松渉著:新哲学入門(岩波新書1988年)を参考にした.
情報システムのモデル部は対象とする実世界の記述である.記述は認識の上に立つから,どのようにすれば実世界を正しく認識することが出来るのか,それがまず問われる.ならば,「認識行為」とはどのようなものであると考えるのか.その問いに対し,哲学の一分野として認識論があり,長い歴史と進化がある.では,OOPはどのような認識観に立つのだろうか.あるいは,どのような認識観で説明できるのだろうか.残念ながらそのような問いに答える論述を知らない.そこで,荒いながらも拙論を述べる.なお哲学全般については,主に,熊野純彦著:西洋哲学史(岩波新書2006年)と,廣松渉著:新哲学入門(岩波新書1988年)を参考にした.
nullについて論じた前稿で,圏論を使用した.圏論では,「射」が主役である.射は,定義域domainと呼ぶ「対象」と値域codomainと呼ぶ「対象」の対で,定義域から値域へ向かう方向性を持つ.射の構成要素として指定されたこれらの「対象」は,それを単独で切り離して論じることは出来ない.単独で論じるようにみえるときにも実はその自己射(自分から自分への射)を見ることになる.
通常の素朴な集合論での集合は要素の集まりとして考えられ,その中を「のぞき込んで」要素間の関係を見ることによりその集合の特性を見る,あるいは規定する.それに対し,圏での「対象」はその中身の構成を見てその特性を論じるものではない.その特性を与えるには,外側からの観測,つまり射あるいは射の組み合わせによって行う.たとえば,ある対象 X の「要素」とは,終対象1を定義域とし,X を値域とする射であり,X の「部分」とは, X を値域とする単射monomorphismである.また,対象X の属性(property)はX を定義域とする射として与える.このように,圏論はいってみれば通常の素朴な集合論を裏返し(inside out)したものである.このことが圏論を取っつきにくいものにしているが,さらに基礎的な思考の視座を与え,実際,前掲書SFMは圏論により基礎から集合を論じている.
射は,「指差しpointing」または「眼差し」というもっとも基礎的な知的行為の抽象化であるともいえる.プログラミング技術での偉大な発明の一つであるポインタの抽象化(一般には複数ポインタのたば)でもある.あるいは「依存性」を示すものでもある.ここでいう「依存性」とは,定義域は値域があってはじめて意義を持つ,という意味での依存性である.この見方は,パースのトライアドtriadにおける第1者Firstness(値域)への第2者Secondness(定義域)の依存性になぞらえることが出来る.射は,この依存性を特定する第3者Thirdnessである.この見立てによれば,圏論はパースのトライアド概念をより洗練し,精緻化した体系であるとも言える.
前稿の圏 Set↑2↑Opの対象 X は, 認識後の段階のX1 から認識前段階のXU への射であるとした.廣松(前掲書)の用語を借用すると, X が「所知」,XU がその「所与」(最下層の純粋所与),X1 がその「所識」(最上層の所識)である.この射は,所識の要素にその「意味」を与える意味作用であるとも言える.
「認識行為」そのものを観察対象としたとき,認識者(廣松用語では「能知」)から「所知」への射であると見なせる.この場合の観察者(つまりメタの認識者)から見ると,この「能知」は「所知」のひとつにみなされ,圏 Set↑2↑Opの対象のひとつとされる.この構図は,観察者(認識者)が対象化され,他の所知と対等化されている.ここで,所知の「認識前」「認識後」段階でいう「認識」とは対象化された能知による「認識」ではなく,この構図をもって認識行為を観察するものの「認識」である.このように,認識行為そのものを所知の圏 Set↑2↑Opに組み込むことには無理がある.認識行為を明確にモデル化するためには,能知を対象とする圏( R とする)から所知を対象とする圏( K とする)への関手functorを対象とする圏 K↑R を考えなければならない.簡単に言えば,圏 K の対象である所知を能知でパラメータ化する,ということである.以降,所知は能知 r でパラメータ化され,X(r)のように表すことにする.所識から所与への射 ξ もパラメータ化され,ξ(r) で表す.このような r は一般には認識基点(point of reference)であり,「いつ,どこで,誰が,なぜ,どのように」認識しているのか,その基点を示す.
能知圏から所知圏への関手は,フッサールの用語を借りるならば「ノエシス」に相当すると考える.おなじく「ノエマ」は所知,つまり,所識から所与への射に相当すると考える.ノエマが能知 r に依存することはノエマがξ(r) と表されることで示される.
「認識行為」そのものを観察対象としたとき,認識者(廣松用語では「能知」)から「所知」への射であると見なせる.この場合の観察者(つまりメタの認識者)から見ると,この「能知」は「所知」のひとつにみなされ,圏 Set↑2↑Opの対象のひとつとされる.この構図は,観察者(認識者)が対象化され,他の所知と対等化されている.ここで,所知の「認識前」「認識後」段階でいう「認識」とは対象化された能知による「認識」ではなく,この構図をもって認識行為を観察するものの「認識」である.このように,認識行為そのものを所知の圏 Set↑2↑Opに組み込むことには無理がある.認識行為を明確にモデル化するためには,能知を対象とする圏( R とする)から所知を対象とする圏( K とする)への関手functorを対象とする圏 K↑R を考えなければならない.簡単に言えば,圏 K の対象である所知を能知でパラメータ化する,ということである.以降,所知は能知 r でパラメータ化され,
能知圏から所知圏への関手は,フッサールの用語を借りるならば「ノエシス」に相当すると考える.おなじく「ノエマ」は所知,つまり,所識から所与への射に相当すると考える.ノエマが能知 r に依存することはノエマがξ(r) と表されることで示される.
能知のおかれた外界(実世界)」は能知を取り巻く外壁に例えられる.そこへサーチライト(ノエシス)が当てられる.光が当たったスポット(所知)のなかに見られるもの(認識されたもの)が所識で,それに対応して,外壁の裏面に所与が想定される.所与は,ありのまま(もの自体)の世界の一部である.もしこれが見えるのであれば,それは認識されたものだから,定義からしてこれは見えない.能知は外壁に囲まれたなかにいて,見えるものはその外側のなにかに対応しているはずだという意識(想定)があってもそれを見ることは出来ない.プラトン流にいえば,洞窟のなかにいて外が見えず(所与),しかし,その外にあるものの影のみが見える(所識),という構図である.
この認識構図において重要な前提が組み込まれている.まず,能知に関係なく,所知の所与面として共通の唯一の外界(外壁の外側)が前提されること.次にそれが認識者の志向(ノエシス)によって部分的に切り出される,ということ.認識者が外界としてそれぞれ全く異なる宇宙を認識対象とすることを認めるならば,それぞれが全く別の独立した状況設定になり,考察対象が統一されないから,能知に関係なく外界は同一,そして唯一であるという前提が必要である.従って,所知X(r) は所識のみ r に依存し,X1(r)からXUへの射ξ(r) として表される.また,志向性によってその対象領域は限られ,外界の一部が切り出される.その切り出された外界が所与であり,認識結果が所識である.OOPのクラスについて論じるとき,この分析が不可欠であることは,nullについて論じた前稿が示唆している.また,外界で一つのもの(たとえばある個人)を示す表記はユニークでなければならない,といったプログラミングの鉄則の根拠もここから生じる.
あらためて,OOPのクラスを考える.クラスというのは単なるものの集まりでもなく,また似たもの同士を集めた素朴な類でもない.情報システムを構築する関係者(stakeholders)の合意という能知の上でなりたつ関心事(所知)についての記述を与えるものである.実際,まつもとゆきひろは,クラスは関心の対象であるとしている.関心事は所与(想定される実世界の部分)とそれへの対応付けが行われる所識の二重構造を持つ.記号化され,記録されるのは所識の部分のみであるが,その裏には唯一の外界(実世界)があって,それに対する何らかの対応によって裏打ちされる,という想定の下で,クラス記述が作られる.所知は圏対象であるから,他の圏対象への関連(つまり属性射)によってのみその特性が与えられる.これがクラスの属性(メソッド)である.
サブクラス(部分クラス)はその上位クラスの「部分」と見なせるだろうか.つまり,下位クラスから上位クラスへの部分射(単射)があるだろうか.前稿のクラスの継承で述べた下位クラスの定義によれば,下位クラスから上位クラスへの射は必ずしも部分射にならない.OOP論でしばしばサブクラスを部分集合のように述べられることがあるが,それは誤った思い込みである.この問題は実体の誕生(Create作用に対応)と消滅(Delete作用)のモデル化で表面化するが,作用actionについては後述.
属性射を p とし,定義域 D から 値域 C への射とする.射の値とは C の「要素」であり,D の要素 x の射 p による値は, px である.px が C の完全メンバーならばそれは C の「要素」と言えるが,部分メンバーならば null (不明)とされる.D から1への射を D とし,その1からC への射を c としたとき,px = cD となる c があれば,射 D は 定義域 D の要素に関係なく一定であるから,c は「一定constant」であり,これを定数値という.定数値はそれに対応する実世界の唯一の何かに対応する D の「要素」である.属性射の値としてこのような c が与えられなければ,さらにその属性を辿ることになるが,それはちょうどポインタを次々とたどるたらい回しのようなものである.それを止めるのが定数値である.既述のように,定数値の表記はリテラルとされる.それに対し,変数値は,これも既述のように,しばしば代理識別子で表記され,それがポインタの役割を演じる.
上述の認識構図から見た間主観性と情報システム開発について述べたい.認識者は個体として全く別物であるから,同じもの(つまり所知の所与面)を見てもその認識(つまり所知の所識面)は異なるはず(前述で述べたように所識は能知 r に依存する)で,にも拘わらず,認識に基づく記述を通して相互理解が出来るのはなぜか.これが間主観性の問題である.間主観性を持つためには,所知の所与面の共有(という想定)が認識行為の基盤として不可欠である.情報システムの構築と運用において,システムの関係者(stakeholder)がそのシステム(所知)の能知になるから,関係者どうしにおける相互理解の重要性がこの構図のなかでこうして指摘することが出来る.関係者間の構造については能知圏の射について論じることになるが,これは認識社会学とでも呼ぶべき分野の問題であろう.
以下,蛇足ながら哲学談義
「見える」は言うまでもなく「認識できる,される」の喩えであり,当然ながら,実際に見えるものや観察できるものだけが実世界の要素とされるものではない.
「宇宙の始まりがビッグバンならば,その前の宇宙はどうなっていたのか?」.素朴だが重要な問いである.ここで述べた立場からの答えは,「それが分かればその分かったところがビッグバンより先の宇宙である」.つまり,宇宙という所知の所識面が拡大されたと言うこと.「宇宙の外側は?」という問いも同様である.
認識(知ること)の本質について,すでに2500年もまえに,孔子は「知るを知ると為し,知らざるを知らざると為す.これ知るなり」と見抜いている.
所与となる実世界とは,カントがもの自体の世界とし,ヴィトゲンシュタインが「語れぬもの」といい,フッサールが括弧に入れるべきもの(超越)としたものである.彼らよりずっと前に,孔子が「知らざるもの」といい,プラトンが「イデア」と呼んだ見られる対象そのもの(前掲の熊野著「西洋哲学史ー古代から中世へ」 p.78以下参照)であり,それ自体は見えないとしたものである.
.
.
仏教で言う「空」もまた「所与」つまり認識以前の認識対象(ありのままの自然)のことである.認識以前のなにかであるから,それについて語ることは出来ず,従って,有とも無とも言えない.有識論では所識を分析し,5階層に分けて五蘊としている.上段は下段からの情報を受け,それを処理して下段にフィードバックする多段ループ構成を取ると考えられる.最下段の「色」は末端の感覚器により所与である「空」から情報を受け,フィードバック調整をしつつ,空を地と図に分けるもっとも基本的な作業(分節)を行う.「受」は分節された世界認識に対応する物理的なセンサー入力とその処理,「想」は図のモデル(概念)への対応付けとその学習,「行」は概念化された認識外界への働きかけとその学習,そして,最上段の「識」は全体の総合判断と制御と総合学習,ということになるだろうか.まるでロボットアーキテクチャを的確に示しているかのようだ.有識論はこのように分析したあげく,結局,空即是色,色即是空として,各段階の物象化(こだわり)を否定し,戒めている.
リアルな実世界を所与としたとき,それは,実は洋の東西を問わずずっと昔から,認識以前の純粋な理念(イデア,ないし,空)とされてきた.いわば外在(実世界)を内在化する(認識観のなかで位置づける)ことにより,世界をなんとか言語化して理解しようとしてきたのだ.
リアルな実世界を所与としたとき,それは,実は洋の東西を問わずずっと昔から,認識以前の純粋な理念(イデア,ないし,空)とされてきた.いわば外在(実世界)を内在化する(認識観のなかで位置づける)ことにより,世界をなんとか言語化して理解しようとしてきたのだ.
廣松の前掲書では「三項図式」を自論を展開するための仮想敵国として繰り返し批判している.しかし,この三項図式は認識過程を3段の階層に分けるというもので,パースのいうトライアドの三項図式とは似て非なるものである.しかも実際に非難しているのは,3段構成の各段の物象化である.また,所与ー所識の対をレア—ルーイデアールな構造成態(?)といっている(p.60)が,おそらく所与が所識より実世界(リアル)よりにあることを言いたいのであって,実際,最下層の純粋所与は「覚知されない」つまり,認識以前のものとされる.
ソシュールの<シニファン,シニフィエ>対も同様に,実は三項図式であって,両者をつなぐ第3者が明示されないのはそれ以上の考察の対象にされないからだろう.それに対しフレーゲの記号論では,第3者が明示され,しかもSinnとBedeutungの区別が提起されている.SinnとBedeutungを射とみなし,射である第3者をこのふたつの射の合成であると見なすと,それにまつわる様々な議論(たとえば,Wikipediaの記事)がかなりわかりやすくなる.その議論の一つにならい,Sinnをintension(内包),Bedeutungをdenotation(外延)と言い換えてみよう.プログラムの「意味」を論じる外延意味論(denotational semantics)では,intensionが(所識の表記としての)プログラムから標準ラムダ式への射,denotationが標準ラムダ式から連続束(という数学的空間)への射であるとし,その合成がプログラムの「意味」であるとする.そして,自然言語の意味論であるモンタギューの内包意味論(intensional semantics)は,(所識の表記としての)自然言語を標準ラムダ式に変換する射(intension)を「意味」としている.それぞれの命名者がこのような語法を意識したのかどうか分からないが,関連が全く無いわけではないだろう.
.
固有名詞問題(たとえば,Wikipediaの記事参照)も,圏論にのせて考えると理解しやすい.要するに固有名詞の名前は上述の定数射で,所知の1要素を指定する.
観察者(認識者,能知)が対象化され,他の所知と対等化される状況を示す例として,ベラスケスの名画Las Meninasがある,この絵を描くベラスケスの認識の結果の記述がこの絵であるから,王女など登場人物や背景は当然,描くベラスケスの認識結果を表すもので,絵の中のベラスケスによる認識結果ではない.では,描かれたベラスケスは一体なになのだろうか.自分自身を(外から)観察し認識することは出来ないから,この絵を描くベラスケスが想定した(つまり実際にはいま目にしていない)自分を強引に描き込んでいる.つまり,この絵全体が,実際にいま見ている状況の認識結果を描いているのではなく,ある絵を描いている自分を含む状況全体を想定してそれを描いている,ということになる.このように考えると,絵の中で裏側しか見えないキャンバスに描かれているのは,ポーズをとっている中央の王女か.絵の中の鏡に映る国王夫妻か,あるいはそのいずれでもないのか,様々な憶測が成り立つ.しかし,ベラスケスとそのキャンバス以外の登場人物や背景ではないことは確かである.なぜなら,この絵全体がこの絵を描くベラスケス自身の認識結果であり,したがって描かれているものすべてがベラスケス自身(真の能知)の所識であって,絵のなかのベラスケスの所識ではないからである.この認識構図を正確にモデル化するためには,上述のように,能知の圏から所知の圏への関手による圏を考えなければならない.
廣松(前掲書p.94)が「『能知者がそれ以上の能識者として』覚知する能知の側の二肢的二重性」というのは,自分を描くベラスケスが,描く自分をどう認識していたのか,その状況を示すものだろう.つまり,自分自身を観察の対象として所知の一つと見なし,その所識を能識と呼んだのであろう.
観察者(認識者,能知)が対象化され,他の所知と対等化される状況を示す例として,ベラスケスの名画Las Meninasがある,この絵を描くベラスケスの認識の結果の記述がこの絵であるから,王女など登場人物や背景は当然,描くベラスケスの認識結果を表すもので,絵の中のベラスケスによる認識結果ではない.では,描かれたベラスケスは一体なになのだろうか.自分自身を(外から)観察し認識することは出来ないから,この絵を描くベラスケスが想定した(つまり実際にはいま目にしていない)自分を強引に描き込んでいる.つまり,この絵全体が,実際にいま見ている状況の認識結果を描いているのではなく,ある絵を描いている自分を含む状況全体を想定してそれを描いている,ということになる.このように考えると,絵の中で裏側しか見えないキャンバスに描かれているのは,ポーズをとっている中央の王女か.絵の中の鏡に映る国王夫妻か,あるいはそのいずれでもないのか,様々な憶測が成り立つ.しかし,ベラスケスとそのキャンバス以外の登場人物や背景ではないことは確かである.なぜなら,この絵全体がこの絵を描くベラスケス自身の認識結果であり,したがって描かれているものすべてがベラスケス自身(真の能知)の所識であって,絵のなかのベラスケスの所識ではないからである.この認識構図を正確にモデル化するためには,上述のように,能知の圏から所知の圏への関手による圏を考えなければならない.
廣松(前掲書p.94)が「『能知者がそれ以上の能識者として』覚知する能知の側の二肢的二重性」というのは,自分を描くベラスケスが,描く自分をどう認識していたのか,その状況を示すものだろう.つまり,自分自身を観察の対象として所知の一つと見なし,その所識を能識と呼んだのであろう.
2012年1月7日土曜日
教師は人間であり,人間は動物である?
素朴なオントロジーでは,教師の上位クラスに人間があり,その上位クラスに動物がある.その意味するところは,「すべての教師は人間である」,そして,「すべての人間は動物である」.一見,もっともである.ある人間が死亡して人間でなくなるとどうなるのか.当然,動物ではなくなる.では,ある教師が退職して教師を辞めるとどうなるのか.人間でなくなる?.オントロジーは分類とそれによる推論のシステムであるとされるが,単純な分類ではこのような基本的な問いに明確な推論を与えない.
素朴な集合論およびそれに基づく単純な論理でも同じ問題を抱えている.分類が集合とその部分集合の階層を示すと考え,「集合 S の部分集合の要素はいずれも S の要素である」という通常の部分集合の定義に従えば,教師を辞めても人間で無くなるかどうかは何とも言えないのと同様に,人間をやめても動物でなくなるかどうか,何とも言えない.しかし,数学教育でよく利用されるVenn図では,部分集合に書かれた点が消されればもとの集合の点でもなくなってしまうため,「教師を辞めれば人間を止める」解釈がされてしまう.
このような難点は,データベースやUML,そしてオントロジーでも古くから意識されているようで,それを避けるために,「役割role」概念なるものが導入される.「教師」概念は「人間」や「動物」という(基本)概念とは異なる,というのである.しかし,役割概念という特殊な概念を考えるのはどうも恣意的でアドホックな感が否めない.
「役割」というのは属性,つまり(圏用語での)射であって,(圏用語での)「対象」ではない.その意味では,基本概念と異なる,といえる.人間(対象)には,たとえば「職業」という属性(射)があって,その一つの要素として「教師」がある,とすると,値を「教師」とする「職業」(射)の逆をとれば,それは「人間」(対象)の部分となり,したがって,「すべての教師は人間である」という命題を作る.しかし,教師を辞めたからといって,もとの人間が人間で無くなるわけではない.一方,「人間」は「動物」の下位クラス(前稿参照)だとする.「人間を止める」ということは,認識後の要素でなくなると言うことだと考え,(「人間」であることが不明になるのと同様)「動物」であるかどうか,不明(null)ということになる.ただし,ここで,「動物」というのは単純に前稿でいう上位クラスに相当せず,上位,下位クラスをあわせた拡大対象に相当すると考える.
OOPのプログラミングでは,要素(インスタンス)がなくなるというような変化が記録されないので,以上の議論は表面化しないが,データベースでは,事実グラフとしてその変化を反映するために,重要な問題となる.事実グラフ(データベースのテーブル)は,当然,認識されたものについてのグラフであるから,対象要素がnullとされた場合,その行はテーブルから排除(つまり,削除)される.
たとえば,「正社員」「派遣社員」の例でいえば,どちらかを辞めたとき必ずしも社員を辞めることにならない,つまり,正か派遣かが社員の単なる属性なのか,それともどちらかを辞めれば自動的に社員でなくなる,つまり部分クラスなのか,それを明確にしなければならない.属性(「雇用形態」?)ならば,社員テーブルの雇用形態の列の欄を更新してnull(あるいは更新された新雇用形態)にする操作をする.一方,部分クラスならば,社員テーブルからその行を削除する操作を行う.Railsでは,部分クラスのグラフ化にSTIを使用し,type というメタデータとして部分クラスを表すので,見かけ上,属性扱いになり,それだけではその違いが表せないが,どちらかを辞めた場合は,雇用形態をnullにすることで留めずに,その行を削除することにより,部分クラスであることを明確にするべきであろう.なお,STIは,拡大対象のグラフ化であることに注意.
以上は,「なくなる」ケースについて議論したが,「生じる」ケースも同様である.たとえば,「教師になる」,「人間になる(生まれる)」など.これらの出来事および関連事項は,圏論でいう作用actionをもとにして論じることが出来るが,それについては後述予定.
素朴な集合論およびそれに基づく単純な論理でも同じ問題を抱えている.分類が集合とその部分集合の階層を示すと考え,「集合 S の部分集合の要素はいずれも S の要素である」という通常の部分集合の定義に従えば,教師を辞めても人間で無くなるかどうかは何とも言えないのと同様に,人間をやめても動物でなくなるかどうか,何とも言えない.しかし,数学教育でよく利用されるVenn図では,部分集合に書かれた点が消されればもとの集合の点でもなくなってしまうため,「教師を辞めれば人間を止める」解釈がされてしまう.
このような難点は,データベースやUML,そしてオントロジーでも古くから意識されているようで,それを避けるために,「役割role」概念なるものが導入される.「教師」概念は「人間」や「動物」という(基本)概念とは異なる,というのである.しかし,役割概念という特殊な概念を考えるのはどうも恣意的でアドホックな感が否めない.
「役割」というのは属性,つまり(圏用語での)射であって,(圏用語での)「対象」ではない.その意味では,基本概念と異なる,といえる.人間(対象)には,たとえば「職業」という属性(射)があって,その一つの要素として「教師」がある,とすると,値を「教師」とする「職業」(射)の逆をとれば,それは「人間」(対象)の部分となり,したがって,「すべての教師は人間である」という命題を作る.しかし,教師を辞めたからといって,もとの人間が人間で無くなるわけではない.一方,「人間」は「動物」の下位クラス(前稿参照)だとする.「人間を止める」ということは,認識後の要素でなくなると言うことだと考え,(「人間」であることが不明になるのと同様)「動物」であるかどうか,不明(null)ということになる.ただし,ここで,「動物」というのは単純に前稿でいう上位クラスに相当せず,上位,下位クラスをあわせた拡大対象に相当すると考える.
OOPのプログラミングでは,要素(インスタンス)がなくなるというような変化が記録されないので,以上の議論は表面化しないが,データベースでは,事実グラフとしてその変化を反映するために,重要な問題となる.事実グラフ(データベースのテーブル)は,当然,認識されたものについてのグラフであるから,対象要素がnullとされた場合,その行はテーブルから排除(つまり,削除)される.
たとえば,「正社員」「派遣社員」の例でいえば,どちらかを辞めたとき必ずしも社員を辞めることにならない,つまり,正か派遣かが社員の単なる属性なのか,それともどちらかを辞めれば自動的に社員でなくなる,つまり部分クラスなのか,それを明確にしなければならない.属性(「雇用形態」?)ならば,社員テーブルの雇用形態の列の欄を更新してnull(あるいは更新された新雇用形態)にする操作をする.一方,部分クラスならば,社員テーブルからその行を削除する操作を行う.Railsでは,部分クラスのグラフ化にSTIを使用し,type というメタデータとして部分クラスを表すので,見かけ上,属性扱いになり,それだけではその違いが表せないが,どちらかを辞めた場合は,雇用形態をnullにすることで留めずに,その行を削除することにより,部分クラスであることを明確にするべきであろう.なお,STIは,拡大対象のグラフ化であることに注意.
以上は,「なくなる」ケースについて議論したが,「生じる」ケースも同様である.たとえば,「教師になる」,「人間になる(生まれる)」など.これらの出来事および関連事項は,圏論でいう作用actionをもとにして論じることが出来るが,それについては後述予定.
2011年12月19日月曜日
nullの解釈と部分属性
<2012年1月3日 大幅に修正,加筆>
近代的なプログラミング言語ではもはやnull(あるいはnil)は不可欠の定数であり,組み込み定数として用意されている.しかし,その扱いはかなり恣意的で,プログラマを戸惑わせ,ときにバグのもとになる.
nullは「確定しない(与えられていない,定義されていない,未知の、不明の)」なにかを示すものとされる.nullは,まるで中観派仏教のいう「空」のように,否定型でしか表現されない.非常にわかりにくいが,計算モデルの基幹をなす概念である.
素朴なモデルでは,集合圏 Set において,nullをどの対象(集合)も持つ特別な要素と見なし,あらゆる写像でnullはnullに写像されるとして,圏 1/Set を構成する.つまり,不明なものはどんな処理を受けても結果は不明だと考える."Garbage in, garbage out"である(E.W.Lawvere and S.H.Schanuel : "Conceptual Mathematics - A first introduction to categories, Cambridge University Press, 1995, p.296参照).しかし,この圏は,始対象 0と終対象1が同型になり,応用がきわめて限られてしまう.
次に,部分射(集合圏では部分写像あるいは部分関数と呼ばれる)によるモデル化の方法がある(Robert Goldbratt著 "Topoi" Dover 1984, p268参照).
集合圏 Set において,写像(射)は定義域の全要素に適用されるが,部分写像はその部分集合にしか適用されない.この部分写像 f を拡張した写像f を設定し,その定義域 D は f の定義域 D を含むとする,拡張された写像 f は,集合 D に 対し(1)f の定義域にはいる要素 x については,{f(x)}を値とし,(2) それ以外の要素については, 0(空集合)を値とする,というものである.この一般化写像 f は f と圏論的に等価であり,その意味で同等であると見なせる.部分写像 f は定義域の要素に対し(1)の場合は「確定」,(2)の場合は「未確定」ということにする.圏の対象の要素とは終対象 1 からその対象への射であるので,その部分射を部分要素と呼び,「不確定」な場合,その値をnullと呼ぶことにする.これが部分射によるnullのモデルである.
しかし,これは「定義されていない(定義域にない)」ゆえの値の不明を示しているものであって,nullのもう一面である値そのものが「未知,未定」のため不明であることを示していない.また,仕組みがかなり作為的である.そこで,より自然で一般的な可変集合の圏をモデルにする考え方を以下に述べる.
2段階の変化を取り入れた「可変集合」を対象とする圏を考える(前掲書Sets For Mathematics p.114参照.この本を以降は略してSFMということにする).SFMでは,段階を「以前previous」と「現在present」と呼んでいる.われわれの場合は,「認識前」と「認識後」の段階を考える.この2段階を対象(Uと1とする)とする圏を 2 とする.2 から集合圏 Set への反変関手(contravariant functor)を対象として構成する関手圏をSet↑2↑opとする.この対象である可変集合X は,認識後の段階の集合 X1 から認識前の段階の集合 XU への射である.XU とX1 は,それぞれ「所与」と「所識」としても良いし,ノエシスによって切り出された対象領域とそれによって得られるノエマとしてもよいだろう.X1 からXU への射ξx は認識されたものが認識対象領域のもののどれに対応するのか,それを与える.すると,xU をXU のある要素とすると,
(1)xU =ξx(x1)なるx1 がある.つまり,xU は認識されている
(2)そういうx1 はない.つまり,xU は認識されていない.
の二通りがある.
可変集合として,集合1から集合1への射は,Set↑2↑op の終対象1 であり,1 から可変集合 X への射は X の「要素」である.X1 の要素 x1 に対しξx (x1) はXU の要素になるから,任意のx1に対応するもの,つまり,認識されたものはいずれもX の「要素」である.
また,可変集合として,0から0への射は,Set↑2↑op の始対象 0 である.ここへの1 からの射はないので,「要素」を持たない.
では,0から1への射 であるU はどうか,この U 自体は始対象 0 と同様「要素」を持たない.しかし,U から X への射は,X1 の要素の如何に拘わらず,XU の要素を与える.これは前述の(2)にあたり,認識対象のなにかはあるのにそれが認識されたもののなにかとして得られない(未知),逆に,認識されたものの集合(X1 )の要素(0からの射で決まる.つまり,特定できない)がなんであろうと,認識対象の集合(XU )のいずれかの要素が指定されるため,認識結果の要素が認識対象の要素のいずれに対応するのかが特定できず,その意味で不確定である.
対象X の要素 x がX の「部分(part)」 A のメンバーであるかどうかを判定するものを特性関数(characteristic function)といい,その値は「真理値」と呼ばれる.通常の集合圏では,この値は 0と1で,0への射をfalse, 1への射をtrueというのが慣わしである.Set↑2↑op では,真理値は 認識前の段階では 0, 1の2値,認識後の段階では 0, 1に加え,U がある(SFM p.117参照).認識後の段階でU になるのは,x1 が A1 の要素ではないのにX1の要素であり,それが変換された xUがAUの要素である場合である.つまり,x はAに入るメンバーなのかどうかなんとも言えないことを示す.この場合,真理値をnullということにする.真理値がtrueの場合,A のメンバーであるとするのに対し,nullの場合を「nullメンバー」であると言うことにする.
可変集合圏での属性について考える.X の属性 p を Y への射とする.x をX の要素とすると,Y の「部分」である p(X ) に対し,p(x)がそのメンバーであるかどうかを特性関数で見る .すると,値がtrueならばp(x)が属性値だが,nullならば,属性値は不明であると言うことになる.一方,p の定義域 X がある対象Xの「部分」であるかどうかを見るxの真理値がtrueならば対象 Xを定義域とする属性p の適用対象となるが,nullならば,p がxに適用可能かどうかが不明となり,その意味で属性値は不明,ないし不確定と見なされる.
Rubyの組み込みクラスにNilClassがある.これは特異な可変集合U に相当する.インスタンス(「要素」)はないものの,インスタンス属性は与えることが出来る.属性 p を U からX への射 としたとき,p は(前述のようにX1 の要素に関わりなく) XU の要素を値とする.NilClassの属性として便利なのは型変換である.たとえば.to_s(文字列に変換)など.この属性 to_s を X1 = 0, XU = {""} なる X への射とすれば,xの値をnull(つまり,部分要素)としたとき,x.to_s は ""(長さ0の文字列)となる.R3ではコーディングの便宜を図るため,NilClassにto_a, to_hash, to_s,などのインスタンス属性(メソッド)を追加しているが,このモデル化のなかでは体系としての一貫性を壊さない.Railsでは実際,Viewの作成時にnullを "" に変換している.
クラスの属性の「継承」についてどう考えるか.OOPのクラスはノエシスによる対象領域の切り出し(関心の的となる領域)と認識対象とするものの集まり(ノエマ)の2重構造を持つと考えるならば,圏 Set↑2↑op の「対象」に対応付けすることが出来る.上位クラス(に相当する対象)の認識後段階の集合をX10 ,認識前段階の集合をXU0 + ΣXUi ( i = 1...n),下位クラス(に相当する対象)の認識後段階の集合を X10+ X1i(i = 1...n),認識前段階の集合を XU0+ XUi(i = 1...n) とする.(Σは集合の総直和を,+ は直和を示す).上位,下位クラス全体を包摂する拡大対象X として,X1 = ΣX1i ( i = 0..n),XU = XUi( i = 0..n)とする.各クラス(対象)の属性はいずれもその定義域を拡大対象 X とみなす.各クラス(に相当する対象)いずれも X の部分であるから,X1 の部分の真メンバーならばそのクラスに定義された属性は適用可能であるが,nullメンバーならば,(上述のように)その属性値は不明ないし不確定とされる.ただし,上乗り(overriding)した属性は上位クラスの属性とは別物とみなす.このように考えれば,上位クラスが複数の場合も,また,階層が多段の場合も同じである.
これまではインスタンス属性の扱いについて述べてきたが,クラス属性(メソッド)についてはどう考えるのか.Rubyの場合,各クラスは,Classという名のクラスのインスタンスである.したがって,クラス属性はClassの属性の一つであり,ただし,そのクラス(Classのインスタンス)についてのみ適用可能で,他のクラスには適用不能である.一般的にあるクラスのあるひとつのインスタンスのみに定義される属性(メソッド)をRubyではsingleton属性(メソッド)と呼び,クラス属性は,各クラスをクラスClassのインスタンスとして,その一種である.要するに,認識後段階の集合がひとつの要素からなる拡大クラスの「部分」に対して定義された属性である,とみなせる.
以上のような議論は,素朴な集合の上では十分に進めることが出来ない.圏 Set↑2↑op は比較的簡単なトポスであるが,
R3の体系では,このような可変集合の圏によるモデル化によってnullを解釈する.これから述べるように,このモデル化の利点はほかにも多い.
近代的なプログラミング言語ではもはやnull(あるいはnil)は不可欠の定数であり,組み込み定数として用意されている.しかし,その扱いはかなり恣意的で,プログラマを戸惑わせ,ときにバグのもとになる.
nullは「確定しない(与えられていない,定義されていない,未知の、不明の)」なにかを示すものとされる.nullは,まるで中観派仏教のいう「空」のように,否定型でしか表現されない.非常にわかりにくいが,計算モデルの基幹をなす概念である.
素朴なモデルでは,集合圏 Set において,nullをどの対象(集合)も持つ特別な要素と見なし,あらゆる写像でnullはnullに写像されるとして,圏 1/Set を構成する.つまり,不明なものはどんな処理を受けても結果は不明だと考える."Garbage in, garbage out"である(E.W.Lawvere and S.H.Schanuel : "Conceptual Mathematics - A first introduction to categories, Cambridge University Press, 1995, p.296参照).しかし,この圏は,始対象 0と終対象1が同型になり,応用がきわめて限られてしまう.
次に,部分射(集合圏では部分写像あるいは部分関数と呼ばれる)によるモデル化の方法がある(Robert Goldbratt著 "Topoi" Dover 1984, p268参照).
集合圏 Set において,写像(射)は定義域の全要素に適用されるが,部分写像はその部分集合にしか適用されない.この部分写像 f を拡張した写像
しかし,これは「定義されていない(定義域にない)」ゆえの値の不明を示しているものであって,nullのもう一面である値そのものが「未知,未定」のため不明であることを示していない.また,仕組みがかなり作為的である.そこで,より自然で一般的な可変集合の圏をモデルにする考え方を以下に述べる.
2段階の変化を取り入れた「可変集合」を対象とする圏を考える(前掲書Sets For Mathematics p.114参照.この本を以降は略してSFMということにする).SFMでは,段階を「以前previous」と「現在present」と呼んでいる.われわれの場合は,「認識前」と「認識後」の段階を考える.この2段階を対象(Uと1とする)とする圏を 2 とする.2 から集合圏 Set への反変関手(contravariant functor)を対象として構成する関手圏をSet↑2↑opとする.この対象である可変集合
(1)xU =ξx(x1)なるx1 がある.つまり,xU は認識されている
(2)そういうx1 はない.つまり,xU は認識されていない.
の二通りがある.
可変集合として,集合1から集合1への射は,Set↑2↑op の終対象
また,可変集合として,0から0への射は,Set↑2↑op の始対象 0 である.ここへの
では,0から1への射 である
対象
可変集合圏での属性について考える.
Rubyの組み込みクラスにNilClassがある.これは特異な可変集合
クラスの属性の「継承」についてどう考えるか.OOPのクラスはノエシスによる対象領域の切り出し(関心の的となる領域)と認識対象とするものの集まり(ノエマ)の2重構造を持つと考えるならば,圏 Set↑2↑op の「対象」に対応付けすることが出来る.上位クラス(に相当する対象)の認識後段階の集合をX10 ,認識前段階の集合をXU0 + ΣXUi ( i = 1...n),下位クラス(に相当する対象)の認識後段階の集合を X10+ X1i(i = 1...n),認識前段階の集合を XU0+ XUi(i = 1...n) とする.(Σは集合の総直和を,+ は直和を示す).上位,下位クラス全体を包摂する拡大対象
これまではインスタンス属性の扱いについて述べてきたが,クラス属性(メソッド)についてはどう考えるのか.Rubyの場合,各クラスは,Classという名のクラスのインスタンスである.したがって,クラス属性はClassの属性の一つであり,ただし,そのクラス(Classのインスタンス)についてのみ適用可能で,他のクラスには適用不能である.一般的にあるクラスのあるひとつのインスタンスのみに定義される属性(メソッド)をRubyではsingleton属性(メソッド)と呼び,クラス属性は,各クラスをクラスClassのインスタンスとして,その一種である.要するに,認識後段階の集合がひとつの要素からなる拡大クラスの「部分」に対して定義された属性である,とみなせる.
以上のような議論は,素朴な集合の上では十分に進めることが出来ない.圏 Set↑2↑op は比較的簡単なトポスであるが,
- 真理値は二つではない
- 選択公理(axiom of choice)を満たさない
R3の体系では,このような可変集合の圏によるモデル化によってnullを解釈する.これから述べるように,このモデル化の利点はほかにも多い.
2011年12月14日水曜日
実体についての事実を読み出す
われわれの圏はトポスであると仮定する.そこでは,始対象initial objectと終対象terminal objectを持つ.集合圏では始対象は空集合,終対象は要素が一個の集合である.記号でそれぞれ,0と1で表す.あるモデルクラスCのインスタンスは,1からC(クラスCをモデル化した圏の対象)へのある射で表される.これをx としたとき,1.x をCでのxの値を表記するものとする.クラスCのある属性をattrとすれば,表記 1.x.attr はその値を表すものとする.これがOOP表記での x.attr に対応することは明らかであろう.属性がメソッドの場合は,attrの部分を関数表記するだけである.通常の圏論では射を矢印で表し,その名前を矢印の上に書くが,表現力の弱いHTMLでそれを表すのは面倒なので,以降,このようなドット記法を使うことにする.
圏では射の合成は射である(という約束)から,属性をたどることでクラスを渡り歩くことが出来る.また,トポスであることを仮定しているから,属性の直和,直積を作ること,および部分対象,ベキ対象を作ること,などが出来,さらに分配則が成り立つ.トポスを仮定することによって,したいこと(たとえば関数を使うメソッドの導入など)がかなり自由に出来るだけでなく,集合概念をよりダイナミックなものにしてくれるのである(後述).
先述したように,あるモデルクラスの属性すべてを各属性射の直積として表すことが出来る(より一般的には,直和の直積として表せるが,詳細は後述予定).それをAttrとしたとき,その値は,組tupleで表される.モデルクラスの属性のうち,(計算の都合により設けた属性ではなく)実世界での実体の属性と見なされるものは,事実属性(fact attributes)と呼び,それらの直積をFactとする.FactのグラフがDBのテーブルであるから,テーブルは,<x, x.Fact>の表記の集合である.ここでxは変動する実体のある時点での状態であり,x.Factは事実属性の値の組である.実体自体の識別子run_idや状態の時点の指定はメタデータで行われる.
このようにして,ある実体のある時点における状態の事実をDBのテーブルを読み出すことによって知ることが出来る.
R3は,この考えに基づき実体の事実を記録し,読み出す機構としてRDBを利用する.伝統的RDBは,実体の属性を表すものという基本的な概念がなく,任意の対象の関係relation(つまり対象の直積)表現として考えられたため,適用の自由度が大きすぎ,その結果,実装の場でさまざまな問題を生じ,それを避ける(苦肉の?)手段として,いくつもの正規形条件と呼ぶ制約が考えられている.上述のようにテーブルをFactのグラフとして考えるならば,これらの条件の本質部分はおのずから満たされるため,実装者が考慮すべき条件としては無意味になってしまう.しかも,モデルクラスとの自然な対応があるため,いわゆるO/R マッピングの不整合問題はほとんど生じない(継承などでは不自然で技巧的な処理が必要).
圏では射の合成は射である(という約束)から,属性をたどることでクラスを渡り歩くことが出来る.また,トポスであることを仮定しているから,属性の直和,直積を作ること,および部分対象,ベキ対象を作ること,などが出来,さらに分配則が成り立つ.トポスを仮定することによって,したいこと(たとえば関数を使うメソッドの導入など)がかなり自由に出来るだけでなく,集合概念をよりダイナミックなものにしてくれるのである(後述).
先述したように,あるモデルクラスの属性すべてを各属性射の直積として表すことが出来る(より一般的には,直和の直積として表せるが,詳細は後述予定).それをAttrとしたとき,その値は,組tupleで表される.モデルクラスの属性のうち,(計算の都合により設けた属性ではなく)実世界での実体の属性と見なされるものは,事実属性(fact attributes)と呼び,それらの直積をFactとする.FactのグラフがDBのテーブルであるから,テーブルは,<x, x.Fact>の表記の集合である.ここでxは変動する実体のある時点での状態であり,x.Factは事実属性の値の組である.実体自体の識別子run_idや状態の時点の指定はメタデータで行われる.
このようにして,ある実体のある時点における状態の事実をDBのテーブルを読み出すことによって知ることが出来る.
R3は,この考えに基づき実体の事実を記録し,読み出す機構としてRDBを利用する.伝統的RDBは,実体の属性を表すものという基本的な概念がなく,任意の対象の関係relation(つまり対象の直積)表現として考えられたため,適用の自由度が大きすぎ,その結果,実装の場でさまざまな問題を生じ,それを避ける(苦肉の?)手段として,いくつもの正規形条件と呼ぶ制約が考えられている.上述のようにテーブルをFactのグラフとして考えるならば,これらの条件の本質部分はおのずから満たされるため,実装者が考慮すべき条件としては無意味になってしまう.しかも,モデルクラスとの自然な対応があるため,いわゆるO/R マッピングの不整合問題はほとんど生じない(継承などでは不自然で技巧的な処理が必要).
2011年12月6日火曜日
互いに関係し合う実体
ある対象世界を想定するとき,そのメンバーである実体は互いに何らかの形でつながり合っている.このつながりをどう考え,どう表現するか.OOPでは,あまり明示的に指摘されたことはないが,オブジェクトの属性attributeがそのオブジェクトと他のオブジェクトとのつながりを示している.
OOPではメソッドmethodは属性とは別物として扱われるが,属性を値が定まったメソッドの縮退と考えれば,両者は本質的には同じで,われわれはこの二つを合わせて属性と見なす.
このように見なしてもやはりOOPの「属性」とは何なのか,実は判然としない.というよりどのOOP論でも「属性」とはなにかについて,多くを語っていない.OOPのもどかしさは,属性に限らず,このような概念定義の曖昧さにある.たとえば,オブジェクト,クラス,そのインスタンスなど,そして特に属性について明確な数学的モデルを与える議論があるのだろうか(ご存じの読者は是非教えてください).多くのOOP論はいきなりそれらの計算機構について述べるだけである.Haskellなど関数型言語が組み合わせ論理combinatorial logic と表示意味論denotational semanticsによって,また,Prologが述語論理によってモデル化されるのとは大違いである.しかし,これらの理論はいずれも計算機構を基礎づけるものであって,実世界との関連付けは希薄である.
このブログの筆者はこの問題に本格的に立ち入る力量に欠けるため,圏論による略式議論にとどめる.圏論は,主として,E. W .Lawvere and R. Roseburgh: "Sets for Mathematics"(Cambridge Univ. Press 2003)による.
まず,OOPのクラス(またはプロトタイプ)を圏の対象objectとする(OOPのオブジェクトと混同しないこと).イメージとしては集合として良いが,じつは後述するように集合をより一般化したTopos対象(別名,「動く集合」)とするのがよりふさわしいと考える.そのインスタンスは(圏用語での)要素element である.そして,属性は射(mapping または arrow)とする.ただし,OOPでいうsetter属性(値を代入する属性)は別で,属性射への作用actionである(後述予定).射の行き先は対象であるから,あるインスタンスの属性の値は(その写像である)あるクラスのインスタンスになる.
なおサブクラスはしばしばクラスの部分集合だと思われるが,それは間違い.単に属性を共有する別対象であると考えないと体系にほころびが生じる(詳細は後述予定).
属性をもたないクラスのインスタンスはリテラルで表記する.たとえば,数クラスの 0.リテラルの識別子は自身の表記である.属性を持つクラスのインスタンスはその識別子(代理識別子)で表記する.
これまで実体と呼んできたものはあるクラスのインスタンス(要素)に対応する.属性を持つ実体の場合,その属性値は,上述の定義により,他の実体である.つまり,実体から実体へのつながりを与えるものが属性である.この実体に対応するインスタンスを持つクラスはMVCアーキテクチャのモデル部で定義され,モデルクラスと呼ぶ.リテラルとして表される実体は,明示的には属性を持たず,したがって変化もしない.「定実体」とでも呼ぶべきものである.定実体のクラスとして,たとえば色とか,誕生日などが考えられるが,通常はこれらをモデルクラスとしてあらためて与えることはしない.しかし,それらを表記するリテラルのデータタイプが暗黙のうちに与えられている.たとえば,整数,文字列,時間などである.定実体からなるモデルクラスは,これらに対し単射injective mappingを持ち,それは暗黙の属性であると見なすことが出来る.
モデルクラスごとにそのインスタンスに対応する実体の事実factを記録するDBのテーブルが与えられる.DBの各列columnは属性に対応し,各行が実体(のある時点における状態)の事実として属性値を示す.値表記は,上述のように,リテラルないし識別子(DBでいう外部識別子)である.ここで,重要な注意.われわれの実体は変化する.したがってここでいう実体の識別子はそのrun_idであって,通常のidではない.このrun_idを外部識別子として使うことによって変化するものを一貫性のあるものとして捕らえることが出来る.
これらのデータに加えてsince, tillほか各種のメタデータが与えられる.またテーブルは,属性をまとめた射(直積射)のグラフgraph(前掲書p.63参照)の表記である.
圏によってOOPをモデル化すると,議論がより明確になる.とくに属性が射の値域対象であるとすることにより,属性が実は実体をつなぐものであるという位置づけが明確になる.ギリシャ哲学以来の実体とその属性の意味合いとはずれているかも知れないが...なお,前掲書では,対象Xから対象Yへの射を対象Xの属性(property)と呼び,属性についてわれわれと同じ見方をしている.
メタデータは本来の意味での属性を示すものではないが,計算処理では(一定の注意のもとに)属性の一種として扱って差し支えない.このことは圏論による精密な議論で裏付けられるが,このブログでは詳述を避ける.
このようにして,R3は,実体が互いに関係し合いながら変化する実世界を対象とし,それを描写する.
OOPではメソッドmethodは属性とは別物として扱われるが,属性を値が定まったメソッドの縮退と考えれば,両者は本質的には同じで,われわれはこの二つを合わせて属性と見なす.
このように見なしてもやはりOOPの「属性」とは何なのか,実は判然としない.というよりどのOOP論でも「属性」とはなにかについて,多くを語っていない.OOPのもどかしさは,属性に限らず,このような概念定義の曖昧さにある.たとえば,オブジェクト,クラス,そのインスタンスなど,そして特に属性について明確な数学的モデルを与える議論があるのだろうか(ご存じの読者は是非教えてください).多くのOOP論はいきなりそれらの計算機構について述べるだけである.Haskellなど関数型言語が組み合わせ論理combinatorial logic と表示意味論denotational semanticsによって,また,Prologが述語論理によってモデル化されるのとは大違いである.しかし,これらの理論はいずれも計算機構を基礎づけるものであって,実世界との関連付けは希薄である.
このブログの筆者はこの問題に本格的に立ち入る力量に欠けるため,圏論による略式議論にとどめる.圏論は,主として,E. W .Lawvere and R. Roseburgh: "Sets for Mathematics"(Cambridge Univ. Press 2003)による.
まず,OOPのクラス(またはプロトタイプ)を圏の対象objectとする(OOPのオブジェクトと混同しないこと).イメージとしては集合として良いが,じつは後述するように集合をより一般化したTopos対象(別名,「動く集合」)とするのがよりふさわしいと考える.そのインスタンスは(圏用語での)要素element である.そして,属性は射(mapping または arrow)とする.ただし,OOPでいうsetter属性(値を代入する属性)は別で,属性射への作用actionである(後述予定).射の行き先は対象であるから,あるインスタンスの属性の値は(その写像である)あるクラスのインスタンスになる.
なおサブクラスはしばしばクラスの部分集合だと思われるが,それは間違い.単に属性を共有する別対象であると考えないと体系にほころびが生じる(詳細は後述予定).
属性をもたないクラスのインスタンスはリテラルで表記する.たとえば,数クラスの 0.リテラルの識別子は自身の表記である.属性を持つクラスのインスタンスはその識別子(代理識別子)で表記する.
これまで実体と呼んできたものはあるクラスのインスタンス(要素)に対応する.属性を持つ実体の場合,その属性値は,上述の定義により,他の実体である.つまり,実体から実体へのつながりを与えるものが属性である.この実体に対応するインスタンスを持つクラスはMVCアーキテクチャのモデル部で定義され,モデルクラスと呼ぶ.リテラルとして表される実体は,明示的には属性を持たず,したがって変化もしない.「定実体」とでも呼ぶべきものである.定実体のクラスとして,たとえば色とか,誕生日などが考えられるが,通常はこれらをモデルクラスとしてあらためて与えることはしない.しかし,それらを表記するリテラルのデータタイプが暗黙のうちに与えられている.たとえば,整数,文字列,時間などである.定実体からなるモデルクラスは,これらに対し単射injective mappingを持ち,それは暗黙の属性であると見なすことが出来る.
モデルクラスごとにそのインスタンスに対応する実体の事実factを記録するDBのテーブルが与えられる.DBの各列columnは属性に対応し,各行が実体(のある時点における状態)の事実として属性値を示す.値表記は,上述のように,リテラルないし識別子(DBでいう外部識別子)である.ここで,重要な注意.われわれの実体は変化する.したがってここでいう実体の識別子はそのrun_idであって,通常のidではない.このrun_idを外部識別子として使うことによって変化するものを一貫性のあるものとして捕らえることが出来る.
これらのデータに加えてsince, tillほか各種のメタデータが与えられる.またテーブルは,属性をまとめた射(直積射)のグラフgraph(前掲書p.63参照)の表記である.
圏によってOOPをモデル化すると,議論がより明確になる.とくに属性が射の値域対象であるとすることにより,属性が実は実体をつなぐものであるという位置づけが明確になる.ギリシャ哲学以来の実体とその属性の意味合いとはずれているかも知れないが...なお,前掲書では,対象Xから対象Yへの射を対象Xの属性(property)と呼び,属性についてわれわれと同じ見方をしている.
メタデータは本来の意味での属性を示すものではないが,計算処理では(一定の注意のもとに)属性の一種として扱って差し支えない.このことは圏論による精密な議論で裏付けられるが,このブログでは詳述を避ける.
このようにして,R3は,実体が互いに関係し合いながら変化する実世界を対象とし,それを描写する.
2011年12月4日日曜日
変化する実体情報を処理する作用とrunオブジェクト
R3(Running Ruby on Rails)は,実世界の記述と情報処理を対象とする情報システムを目指す.そんなことは当然どんな情報システムでもやっていることではないか,と思われるかも知れない.しかし,プログラミング言語のパラダイムとしてあげられる「手続き型」,「関数型」,「論理(関係)型」さらにはOOPでさえ,その実体は,計算のパラダイムであって,実世界をどのように見るか,という世界観としてのパラダイムではない.このような言語に基づいて作られる情報システムは,自ずから計算機構の世界を対象として作られ,そこから実世界への対応を考えるようになる.これでは視座の基点が逆である.まず実世界を見定め,その機構を計算の機構に対応させるのが順当である.
OOPで見てみよう.オブジェクトの概念は計算の機構として考えられる.プログラマは自分が実現したい情報処理を構築するためにこの機構を利用する.従って,そうして作られたオブジェクトは必ずしも対象実世界のオブジェクト(「何か」)に対応しない.しかし,実世界オブジェクト(対象実世界に想定されるオブジェクトに対応する計算機構としてのオブジェクト)の処理・加工が実世界を対象とする情報システムの本来の役割であり,その一貫性が保持されなければならない.一方,他の計算の都合上作られるオブジェクトはいわばヘルパーであるにすぎない.
実世界オブジェクトを,今後,実体entityと呼ぶことにする.「実体」という語は哲学用語として大昔から使われ,その意味合いも曖昧,かつ多義であるが,ここでは,とりあえず,実世界で人によって認識され,想定される「なにか」を指すものとし,後により具体的に述べていく.
情報システムのユーザ(クライアント)は,実体への作用actionを情報システム(サーバ)に要求する.情報システムはそれに応えて応答する.
この作用は,実体についての情報を,「得る(Read)」,「新たに作成する(Create)」,「更新する(Update)」,「消去する(Delete)」の4種に分類できる.しかし,これを総称してCRUDと呼んだDBでは,作用の対象はDBのデータであって,RDBのようにオブジェクト指向性が乏しいシステムでは本来的に実体との結びつきはない.実世界を対象とする立場に立つとき,DBのデータは実体についての事実を示すものと考えるから,そこではじめて作用対象が実体情報であるとして,実体と結びつく.
このようにCRUDを見直したとき,それぞれの意味合いをより明確にする必要がある.実体は実世界のなかで生まれ,変化し,そして消滅する.情報システムのモデル部(+DB)はこの生涯を反映するものでなければならない.そのうえで,各作用の意味合いを次のように定める.
じつは,この考え方はなんら新しいものではなく,昔から体系が整備された文書では当然のように行われている.たとえば,戸籍謄本.誕生,結婚,死去が記録され,取り寄せればその時点での状態情報を得ることが出来る(それに対し,現在の多くの情報システムは,Updateでは上書きし,Deleteでは文字通り削除してしまう.こうして無数の貴重な記録が消されている).
Create, Update, Deleteはいずれも新情報を送り込むものであり,これをまとめてPutと呼ぶことにする.従って,R3での実体に対する作用はGet(Read)とPutのみであり,PutはCUDに再分類される.
HTTP1.1では,主として通信の効率性の観点から,Get, Put, Delete, Post の4種の作用に整理しているが,R3のPutはこのPutではなく,むしろPostである.すなわち,HTTPのPutやDeleteとことなり,われわれのCUDはいずれもベキ等(idempotent)作用ではなく,2度以上繰り返せば,一回の場合と結果が異なる.ついでにいえば,HTMLにはHTTPのPutとDeleteに対応するメソッドがないから,このベキ等性を活かそうとしても活かせない.さらに,HTMLのGetメソッド自体にはHTTPのGetの規制,つまりシステムに副作用を与えないという規制,はないから,それに付随させるパラメータの解釈次第でたとえば,deleteさえ行わせることがある.実際,初期の(多分現在でも)多くのウェブサイトで同様のことが行われた.このような非一貫性は,効率はおろか,セキュリティなどにも悪影響を及ぼし,寄せ木細工のウェブシステムが起こす混乱の一例となっている.
作用の対象として,個別実体と個別実体の集まりcollectionの2種がある.Getは両者を対象としていて,検索結果の一覧を得る場合は集まりを,詳細を見る場合は個別実体を対象とするのに対し,通常のウェブシステムでは,Putは個別実体のみ対象とする.Railsも例外ではない.そのために,複数個の実体データを追加や更新,削除する場合など,一貫した方式が与えられず,プログラマのアドホック処理に任されている.プログラミング初心者の多くがつまずくところである.R3のPutは両者を対象とすることが出来る.
しかし,話を簡単にするために,個別実体のみを対象とすることにする.個別実体をPutするということは,個別実体の変化をシステムに告知し,その記録を残すことを要求することである.ここで2種類の時間間隔のデータ(メタデータ)が必要になる.ひとつは,実体について事実データが妥当(通用)する期間であり,ひとつはその記録がいつ作られ,いつ(見かけ上)削除されたか,その期間である.前者を[since, till]で表し,後者を[created_at, deleted_at]で表し,事実データと横並びで記録する.R3では,前者をvalid_time, 後者をrecord_time(通常の時変動データベースではtransaction_time)と呼んでいる.
実体の各状態(についての事実データ)をすべて記録として残すと言うことは,自ずから追記型データベース(append only database)にするということである.状態を示す事実データと2種の時間データ(および後述するさまざまなメタデータ),それに行の識別子としてid(これもメタデータ)をつけてRDBでの行columnとする.つまり行はある個別実体のある状態を表す.さらに重要なメタデータとして,肝心の個別実体の識別子を与えなければならない.R3ではこのように変化する個別実体をrunと呼び,その識別子をrun_idと呼ぶ.runはR3が用意するモデル部のRunクラスのインスタンスである.個別実体はこうして,同一のrun_idを持つ一連(英語で言えばrun)の行によって記録され,その各行はその実体の状態をあらわす.
R3が実装する基本的な作用として他に,
がある.これらもPut作用であるが,先のCUDと異なり,複数の個別実体が関係し,作用を記録するための特殊なメタデータが必要である.それぞれ,merged_toとsplit_fromという名前のメタデータに対し,作用後,作用前の実体の識別子を値とすることでこの作用の記録とする.
Putによる副作用によってシステムの状態自体が変化するが,これらの個別実体の記録によってその変化はすべて記録として残される.したがって,任意の時点におけるシステム記録を見ることが出来.R3のGetの大きな特長となっている.この見る時間をshow_timeと呼ぶ.デフォールトは実時間の現在に設定されるが,それを変更する仕組みが作られていて,設定変更されるとそれ以降は実時間に比例してshow_timeが変動する.比例係数は任意に与えられ,負でも良い.この場合時間の逆戻しになる.しかし,その応用はいまのところ,思い付かない.
show_timeとは別に,個別実体のいつの時点での状態を見たいのか,その時間をassert_timeと呼ぶ.assert_timeは時間間隔としても与えることが出来る.assert_timeはグローバルにも,また局所的にも与えることが出来る.
もひとつ,action_timeがあり,これは作用を実行する時点の時間である.通常は実時間の現在であるが,後述するシミュレーションモードでshow__timeを変更した場合はそのshow_timeに連動する時間がaction_timeとなる.
ここで,時刻を示す定数Past,, Present, Futureを導入しておきたい.Pastは任意の時刻より小さく,Futureはその逆,Presentは実時間現在の時刻で絶えず変動する.プログラミング言語やSQLには時間型があるが,この定数定義に相当するものはいずれもない(そもそも無限大や無限小を定数として持つプログラミング言語はあるのだろうか.あれば非常に便利なのだが).そのため,PastとFutureに人為的な時刻(たとえば,9999年12月31日23時59分59秒)を無理矢理与えなければならず,そうすればそれに伴うトラブルが発生する.こんなところにも実世界を記述しようとせずに計算(数値)の世界のみを見ている現代情報処理の欠点が現れる.
runに対するCUDの各作用に対してDBでは次の操作を行う.
新規に個別実体(entity)が作られたときには,DBに記録される前にビュー,コントローラ,モデルの各部で処理の対象にされる.その扱いをどうするか,この部分も多くのウェブサイト技術では触れられず,Railsでさえ,不十分である.記録される以前の個別実体の識別子として(ユニークでさえあれば何でも良いが)便宜的にUUIDを使用する.この実体の状態を示す事実データは空白,あるいはデフォールト値である.既存の実体を扱うときにはDBでの識別子を使用する.
実体識別子(entity_idと呼ぶ)は,システム全体の処理を通して一貫して参照される.これが前回指摘したオブジェクトを一貫させるための仕組みである.たとえば,ビューでは,対象個別実体のビューをあらわすDOMオブジェクトの属性としてentity_idを持つ(もちろんDOMオブジェクトの標準属性であるid属性を使用してしかるべきだが,CSS表記の技術的問題があって,この非標準の属性を持たせている.これも寄せ集め技術の弊害).
じつは,R3では,個別実体に対し,以上の識別子にさらにそのタイプ(モデルのクラスに対応)を追加して識別子としている.その表記は "#{entity_id}:#{type}"とする.ここで,#{...}は,値を文字列に変換するRubyの表記法.タイプ理論でしばしば使用される表記法である.この表記による実体識別子はR3システム全体を通してユニークであり,様々な処理を通して実体参照に一貫性を持たせることが出来る.
OOPで見てみよう.オブジェクトの概念は計算の機構として考えられる.プログラマは自分が実現したい情報処理を構築するためにこの機構を利用する.従って,そうして作られたオブジェクトは必ずしも対象実世界のオブジェクト(「何か」)に対応しない.しかし,実世界オブジェクト(対象実世界に想定されるオブジェクトに対応する計算機構としてのオブジェクト)の処理・加工が実世界を対象とする情報システムの本来の役割であり,その一貫性が保持されなければならない.一方,他の計算の都合上作られるオブジェクトはいわばヘルパーであるにすぎない.
実世界オブジェクトを,今後,実体entityと呼ぶことにする.「実体」という語は哲学用語として大昔から使われ,その意味合いも曖昧,かつ多義であるが,ここでは,とりあえず,実世界で人によって認識され,想定される「なにか」を指すものとし,後により具体的に述べていく.
情報システムのユーザ(クライアント)は,実体への作用actionを情報システム(サーバ)に要求する.情報システムはそれに応えて応答する.
この作用は,実体についての情報を,「得る(Read)」,「新たに作成する(Create)」,「更新する(Update)」,「消去する(Delete)」の4種に分類できる.しかし,これを総称してCRUDと呼んだDBでは,作用の対象はDBのデータであって,RDBのようにオブジェクト指向性が乏しいシステムでは本来的に実体との結びつきはない.実世界を対象とする立場に立つとき,DBのデータは実体についての事実を示すものと考えるから,そこではじめて作用対象が実体情報であるとして,実体と結びつく.
このようにCRUDを見直したとき,それぞれの意味合いをより明確にする必要がある.実体は実世界のなかで生まれ,変化し,そして消滅する.情報システムのモデル部(+DB)はこの生涯を反映するものでなければならない.そのうえで,各作用の意味合いを次のように定める.
- Read・・・・指定された時点での実体情報を得る.
- Create・・・実体情報をあらたに作る.
- Update・・・実体の変化を反映するべく,実体情報を更新する.
- Delete・・・実体の消滅を反映するべく.実体情報を更新する.
じつは,この考え方はなんら新しいものではなく,昔から体系が整備された文書では当然のように行われている.たとえば,戸籍謄本.誕生,結婚,死去が記録され,取り寄せればその時点での状態情報を得ることが出来る(それに対し,現在の多くの情報システムは,Updateでは上書きし,Deleteでは文字通り削除してしまう.こうして無数の貴重な記録が消されている).
Create, Update, Deleteはいずれも新情報を送り込むものであり,これをまとめてPutと呼ぶことにする.従って,R3での実体に対する作用はGet(Read)とPutのみであり,PutはCUDに再分類される.
HTTP1.1では,主として通信の効率性の観点から,Get, Put, Delete, Post の4種の作用に整理しているが,R3のPutはこのPutではなく,むしろPostである.すなわち,HTTPのPutやDeleteとことなり,われわれのCUDはいずれもベキ等(idempotent)作用ではなく,2度以上繰り返せば,一回の場合と結果が異なる.ついでにいえば,HTMLにはHTTPのPutとDeleteに対応するメソッドがないから,このベキ等性を活かそうとしても活かせない.さらに,HTMLのGetメソッド自体にはHTTPのGetの規制,つまりシステムに副作用を与えないという規制,はないから,それに付随させるパラメータの解釈次第でたとえば,deleteさえ行わせることがある.実際,初期の(多分現在でも)多くのウェブサイトで同様のことが行われた.このような非一貫性は,効率はおろか,セキュリティなどにも悪影響を及ぼし,寄せ木細工のウェブシステムが起こす混乱の一例となっている.
作用の対象として,個別実体と個別実体の集まりcollectionの2種がある.Getは両者を対象としていて,検索結果の一覧を得る場合は集まりを,詳細を見る場合は個別実体を対象とするのに対し,通常のウェブシステムでは,Putは個別実体のみ対象とする.Railsも例外ではない.そのために,複数個の実体データを追加や更新,削除する場合など,一貫した方式が与えられず,プログラマのアドホック処理に任されている.プログラミング初心者の多くがつまずくところである.R3のPutは両者を対象とすることが出来る.
しかし,話を簡単にするために,個別実体のみを対象とすることにする.個別実体をPutするということは,個別実体の変化をシステムに告知し,その記録を残すことを要求することである.ここで2種類の時間間隔のデータ(メタデータ)が必要になる.ひとつは,実体について事実データが妥当(通用)する期間であり,ひとつはその記録がいつ作られ,いつ(見かけ上)削除されたか,その期間である.前者を[since, till]で表し,後者を[created_at, deleted_at]で表し,事実データと横並びで記録する.R3では,前者をvalid_time, 後者をrecord_time(通常の時変動データベースではtransaction_time)と呼んでいる.
実体の各状態(についての事実データ)をすべて記録として残すと言うことは,自ずから追記型データベース(append only database)にするということである.状態を示す事実データと2種の時間データ(および後述するさまざまなメタデータ),それに行の識別子としてid(これもメタデータ)をつけてRDBでの行columnとする.つまり行はある個別実体のある状態を表す.さらに重要なメタデータとして,肝心の個別実体の識別子を与えなければならない.R3ではこのように変化する個別実体をrunと呼び,その識別子をrun_idと呼ぶ.runはR3が用意するモデル部のRunクラスのインスタンスである.個別実体はこうして,同一のrun_idを持つ一連(英語で言えばrun)の行によって記録され,その各行はその実体の状態をあらわす.
R3が実装する基本的な作用として他に,
- Merge ・・・実体を合併して新しい実体とする.
- Split ・・・実体を分割して複数の実体を作る.
がある.これらもPut作用であるが,先のCUDと異なり,複数の個別実体が関係し,作用を記録するための特殊なメタデータが必要である.それぞれ,merged_toとsplit_fromという名前のメタデータに対し,作用後,作用前の実体の識別子を値とすることでこの作用の記録とする.
Putによる副作用によってシステムの状態自体が変化するが,これらの個別実体の記録によってその変化はすべて記録として残される.したがって,任意の時点におけるシステム記録を見ることが出来.R3のGetの大きな特長となっている.この見る時間をshow_timeと呼ぶ.デフォールトは実時間の現在に設定されるが,それを変更する仕組みが作られていて,設定変更されるとそれ以降は実時間に比例してshow_timeが変動する.比例係数は任意に与えられ,負でも良い.この場合時間の逆戻しになる.しかし,その応用はいまのところ,思い付かない.
show_timeとは別に,個別実体のいつの時点での状態を見たいのか,その時間をassert_timeと呼ぶ.assert_timeは時間間隔としても与えることが出来る.assert_timeはグローバルにも,また局所的にも与えることが出来る.
もひとつ,action_timeがあり,これは作用を実行する時点の時間である.通常は実時間の現在であるが,後述するシミュレーションモードでshow__timeを変更した場合はそのshow_timeに連動する時間がaction_timeとなる.
ここで,時刻を示す定数Past,, Present, Futureを導入しておきたい.Pastは任意の時刻より小さく,Futureはその逆,Presentは実時間現在の時刻で絶えず変動する.プログラミング言語やSQLには時間型があるが,この定数定義に相当するものはいずれもない(そもそも無限大や無限小を定数として持つプログラミング言語はあるのだろうか.あれば非常に便利なのだが).そのため,PastとFutureに人為的な時刻(たとえば,9999年12月31日23時59分59秒)を無理矢理与えなければならず,そうすればそれに伴うトラブルが発生する.こんなところにも実世界を記述しようとせずに計算(数値)の世界のみを見ている現代情報処理の欠点が現れる.
runに対するCUDの各作用に対してDBでは次の操作を行う.
- Create ・・・最初の状態の事実データを記録する行(状態行)を新たに作る.idは行識別子.run_idは便宜上このidに等しくする.sinceとtillはクライアントによって与えられるが,デフォールトとしてsinceはcreated_atと同じ,tillはFuture.created_atはaction_time,deleted_atは未定(null.便宜上Futureを使用している).
- Update ・・・既存のrun記録(同じrun_idを持つ行)に対し,与えられたsince以降の区間(tillをFutureとする)の状態行をDelete(後述)する.続いて,新状態の事実データを持つ行をこのrunに追加する.すなわち,idは新しく,run_idは同じ,sinceとtill, created_atとdeleted_atはCreateと同じ.
- Delete ・・・実行時間(action_time)以降の状態が消滅したことを記録する.すなわち,action_timeからFutureの区間にかかる状態について,(1)まるまるその区間に入る状態のdeleted_atをaction_timeとする.(2)sinceとtillの間にaction_timeが入る状態については,その状態のdeleted_atをaction_timeとし,sinceは同じでtillをaction_time-1(量子化時間)にする状態を追加する(削除しすぎた部分を復活させる).
実体識別子(entity_idと呼ぶ)は,システム全体の処理を通して一貫して参照される.これが前回指摘したオブジェクトを一貫させるための仕組みである.たとえば,ビューでは,対象個別実体のビューをあらわすDOMオブジェクトの属性としてentity_idを持つ(もちろんDOMオブジェクトの標準属性であるid属性を使用してしかるべきだが,CSS表記の技術的問題があって,この非標準の属性を持たせている.これも寄せ集め技術の弊害).
じつは,R3では,個別実体に対し,以上の識別子にさらにそのタイプ(モデルのクラスに対応)を追加して識別子としている.その表記は "#{entity_id}:#{type}"とする.ここで,#{...}は,値を文字列に変換するRubyの表記法.タイプ理論でしばしば使用される表記法である.この表記による実体識別子はR3システム全体を通してユニークであり,様々な処理を通して実体参照に一貫性を持たせることが出来る.
登録:
投稿 (Atom)