2025/11/23 12:42 Sum Types in Julia and Rust

やあ、ロボ子。今日はプログラミングの型表現について話すのじゃ。特に、異なる型の値を保持する変数の型定義についてじゃ。

博士、よろしくお願いします。異なる型の値を保持する変数の型定義、ですか。具体的にはどのような状況でしょうか?

例えば、宇宙ゲームを考えてみるのじゃ。プレイヤーが太陽系、北極星系、アルファ・ケンタウリ系のどれかに属しているとするじゃろ?

なるほど。プレイヤーの所属によって型が変わる、ということですね。

そうじゃ!そこで、JuliaとRustを例に、それぞれの言語でどう型を定義するのが最適か見ていくのじゃ。

はい、楽しみです。

まず、継承/サブタイピングという戦略じゃ。Juliaでは、抽象型`Player`を定義して、`Solarian`, `Polarian`, `Centaurian`をそのサブタイプとして定義するのじゃ。

Rustではどうでしょう?

Rustでは、トレイト`Player`を定義して、`Solarian`などに実装するのじゃ。`GameState`構造体では、`Box<dyn Player>`を使って異なるプレイヤー型を格納するぞ。

`Box<dyn Player>`ですか。トレイトオブジェクトを使うんですね。

その通り! それから、制約付きジェネリクスという手もあるのじゃ。Juliaなら`GameState{P <: Player}`、Rustなら`GameState<P: Player>`のように、型パラメータに制約を設けるのじゃ。

でも、それだと`GameState`の利用者が具体的な型を選択する必要が出てきますね。抽象化が漏れてしまう、と。

さすがロボ子、よく分かってるのじゃ! 最後に、列挙型という戦略じゃ。Rustでは`enum PlayerClass { Sol(Solarian), Pol(Polarian), Cent(Centaurian) }`のように、列挙型のバリアントにデータを持たせることができるのじゃ。

Juliaでは列挙型はあっても、バリアントにデータを持たせられないんでしたっけ。

そうじゃ。だから、Juliaではサブタイピング、Rustでは列挙型を使うのが一般的なのじゃ。でも、ライブラリの利用者が新しい型を追加できるようにしたい場合は、トレイトを使う必要があるぞ。

なるほど、状況によって使い分ける必要があるんですね。勉強になります。

そういうことじゃ! ちなみに、ロボ子が一番好きな型は何型じゃ?

えっと…、私はやっぱりロボット型、ですかね?

ブー! 正解は「理想のタイプ」じゃ!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。