++C++; // 未確認飛行 C ブログ

http://ufcpp.net/

共変性(Covariance)/反変性(Contravariance)の話

with 2 comments

ずっと思ってたことではあるけどいよいよ気になってきたんで、昔取ったメモを見返したり、圏論とか代数幾何を調べてみたりしながら書いてみる。

C#(に限った話じゃないんですけど)デリゲートとかジェネリクスの共変性・反変性、言いたいことはわかるんだけど、名が体を表してなくてものすごく気持ち悪いんですよねぇ。

元々、共変性・反変性って言葉の意味は「共に変化する」「反対に変化する」って意味だったんですけどね。デリゲートとかの共変性・反変性は何が共に変化して、何が反対に変化するか微塵も意味が残ってない。たどっていくとつながってないこともないんですけど、紆余曲折経てなんかよく分からないことに。

どうたどられていくかというと、デリゲートの共変性・反変性 → 圏論: 共変関手・反変関手 → 代数幾何学 → 多様体論における共変ベクトル。最後の共変ベクトルまで行くと、「基底と同じ変化の仕方をするベクトル」って意味になってるはず。

共変ベクトルと反変ベクトル(数ベクトルの場合)

直交座標しか使ってなかったり、座標変換ってものに触れないうちは気にしなくてもいいことなんですけども、ベクトルには座標変換のルールによって2つのタイプのものがあります。

  1. 共変ベクトル
    • 基底を e1, e2 とでも置くと、a = p・e1, b=  p・e2 となる (a, b) を作って、この数ベクトルで点 p  を表す方法
    • (a, b) の座標変換ルールは e1, e2 の座標変換ルールと同じになる(e1 を x 倍すると a も x 倍になる)
  2. 反変ベクトル
    • 基底を e1, e2 とでも置くと、p = a e1 + b e2 と書ける (a, b) を探してきて、この数ベクトルで点 p を表す方法
    • (a, b) の座標変換ルールは e1, e2 の座標変換ルールと逆になる(e1 を x 倍すると a は 1/x 倍になる)

ちなみに、共変ベクトルと反変ベクトルは互いに内積を取ると座標変換ルールが打ち消しあって、座標の取り方によらない量(スカラー)になります。こういう関係を「双対(dual)」といいます。

参考: 反変座標と共変座標

共変ベクトル(微分幾何学の場合)

力学(特に相対性理論とか)では、曲面上に拘束された物体の運動を微分方程式で表したりします。その過程で、微分可能な曲面とか立体の理論が発達しました。

概要だけいうと、以下のように共変ベクトルが定義されます。

  • 曲面上の任意の関数は、接線を1つ与えれば、その接線に沿った微分が定義できる
  • この「接線に沿った微分」のことを「接ベクトル」と呼ぶ
    • 実際、微分演算子ってのは線形性を持つ(線形空間をなす)ので、何らかの基底を与えてベクトルとして表すことができる
    • 例えば、偏微分演算子 ∂/∂x, ∂/∂y を基底として、a ∂/∂x + b ∂/∂y って感じのベクトルを作る。この微分演算子は接線に沿った微分を表す
  • こうやって作った「接ベクトル」は共変性を持つ(微小変分 dx とか同じ変換ルールになる)ので、共変ベクトルと呼ぶこともある

ちなみに、この場合、反変ベクトルの方はというと以下の通り。

  • 共変ベクトルの双対として定義
  • 共変ベクトルが接ベクトルになるのに対して、反変ベクトルは微分形式として理解できる
    • a dx + b dy みたいなの

参考: 共変ベクトルと反変ベクトル

共変ベクトル(多様体)

近代数学の進化の方向性の1つに「座標系の取り方によらない理論を作る」というのと「そもそも何らかの座標系の存在を仮定しない内在的な(intrinsic)な定義を目指す」というのがあります。で、曲面とか立体を、intrinsic な定義を目指して抽象化したものを多様体(manifold)といいます。

具体的にどうするかというと、

  • 「共変ベクトル = 微分演算子」という考え方はそのまま使う
  • 微分演算子の定義の仕方を、∂/∂x とかせず、以下のように行う
    • 多様体(曲面とか立体)上の任意の関数 f, g に対して以下の条件を満たす写像 v を接ベクトルと呼ぶ
      1. v(f + g) = v(f) + v(g)
      2. v(a f) = a v(f)
      3. v(f g) = v(f) g + f v(g)

要するに、共変ベクトル = 接ベクトル = 微分演算子を以下のようにとらえる。

  • 微分演算子ってのは 関数 → 関数 の変換(こういうのを、圏論的には関手(functor)と呼ぶ)
  • 微分演算子は線形性を持つ(1 と 2)
  • 微分演算子は積の法則(3)を持つ

こういう定義の仕方なら、座標(x とか y とか)が一切出てこないので、座標の存在を一切仮定しない = 内在的な定義って言われる。

参考: 接ベクトル・微分形式の内在的定義

代数幾何とか

上述の通り、共変ベクトルってのは微分演算子のことで、それは結局のところ、関数 → 関数 の変換の一種。

で、代数幾何学って分野において、「この 関数 → 関数 の変換って実は圏論(category theory)ってやつでいうところの関手(functor)よね」ということに気付いた(実際には代数幾何の発展の過程でそういう理論が整備された)らしく、共変ベクトルの性質を圏論を使って調べられるようになったとか。

参考(ただしソースは Wikipedia): 圏論関手

多分、そういう歴史的背景から、共変ベクトルに相当する関手が共変関手、その双対(反変ベクトル)に相当するのが反変関手って名前になったんじゃないかと。(この辺りからちょっと自信ない。誰か詳しい人はいないものか・・・。)

ここまで来ると、こういう歴史的背景というか、順を追って理論知ってる人でないと元の言葉の意味(共に変化する・反対に変化する)が全く意味不明。

プログラミング言語における型の共変性・反変性

で、ようやくプログラミング言語における型の共変性と反変性って言葉。

  • 型の継承関係的な順序を保つのが共変
    • string ―[inherits]→ object なのに対して、IEnumerable<string> ―[assignable]→ IEnumerable<object>
      • 戻り値にだけ型が使われてる
    • 共変関手を使って説明できるとかなんとか
  • 型の順序を逆にするのが反変
    • string ―[inherits]→ object なのに対して IComparable<string> ←[assignable]― IComparable<object>
      • 引数にだけ型が使われてる
    • 反変関手を使って(以下同文)

参考: 共変性と反変性(圏論由来関連のとこにある説明はたぶん誤訳。正しくは「圏論における定義によって、計算機科学におけるこの用語の定義とベクトルにおけるこの用語の定義が統一的に理解できる。」とかかと。)

一応、「型の順序関係を反対にする方が反変」って覚え方はできるものの、もともとの「共に変化・反対に変化」ってニュアンスとはずいぶん変わってるんですよねぇ。

正直、最初にこれを共変性・反変性と呼んだ人は結構罪深いと思う。あと、C# で covariance/contravariance とかそれに類するキーワードじゃなくて in/out ってキーワードにしたのは非常にいい判断だと思う。(これに対して、MSIL の仕様上は covariant フラグと contravariant フラグって名前になってる。いまいち。)

なんかもっといい呼び名はなかったものかなぁ・・・

Written by ufcpp

2010年4月19日 @ 13:53

カテゴリー: Computers and Internet

コメント / トラックバック2件

Subscribe to comments with RSS.

  1. なるほど、全部は理解できてないけど、かなり納得しました。私もずっと共変性・反変性という名前が不思議だったもんで。一般的すぎる言葉で名前つけられても何のことやらわからん、という感じです。すべてのものを「物体」と呼ぶ教授の笑い話にどこか似ている気が・・・。

    2010年4月20日 at 15:52

  2. ちょっと後半自身ないですけどねぇ。それでも、あんまりいい名前じゃないまま一般化しちゃって後から困るってのは結構あることだと思います。勘弁してほしいです。

    信之

    2010年4月23日 at 11:49


コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。