toshiki

Rustの型で「呼ぶ順番」を守らせる — Typestateパターン

· Hacker News #130

Rustのtypestate/newtypeパターンで状態機械を型に埋め込み、不正な状態遷移をコンパイル時に排除する論文とHNでの議論。

  • #rust
  • #typestate
  • #newtype
  • #state-machine
  • #type-safety

#なぜ今日これを選んだか

Rust学習(#130)の最終ゴールは「センサーをRustで読み取る」こと。センサーは「初期化→設定→計測」という順番を守らないと壊れる典型的な状態機械で、まさにこのパターンの出番です。「Rustは何が嬉しいのか」を一言で答えられる材料として、今日はこの記事を選びました。

#要点

  • Typestate は「状態」を型パラメータで表す手法。Sensor<Uninit>init()Sensor<Ready> のように、遷移は「前の状態を消費して次の状態を返す」関数で表現する。順番を間違えたコードは実行前にコンパイルエラーになる
  • Newtypestruct UserId(u64) のように既存の型を薄く包み、UserIdOrderId を取り違えるミスを型で防ぐ。Typestateの「状態タグ」もこの応用
  • HNの議論では「不正な状態を表現不可能にできる」と評価される一方、論文自身が認めるボイラープレート増加と可読性低下が懸念点。遷移が多い状態機械では、素直な enum + match やトレイト設計の方が扱いやすい場面もある。Axumのルーター構築などが実例として挙がった

#自分にとっての示唆

Rustlingsやthe Bookで「所有権」「ジェネリクス」を学ぶとき、「これは何のためにあるのか」が分かると定着が段違いになります。Typestateは所有権(前の状態を move で消費する)とジェネリクス(Sensor<S>)の合わせ技で、両方の存在意義を一度に体感できる題材です。次のRust30分(明日・月曜)は、struct Sensor<S>Uninit / Ready の2状態だけ持たせた最小の例を写経してみるのが具体的なアクション。センサー読み取りの本番でも、そのまま設計の骨格になります。やり過ぎは可読性を落とすという議論も、「型で守るのは壊れると痛い遷移だけ」という線引きの判断材料として覚えておきたいところです。