ブログ

Elixir v1.20 リリース:既存のコードを壊さずに「確実なバグ」を見つける漸進的型付けの導入

Elixir の公式ブログで公開された Elixir v1.20 released: now a gradually typed language という記事を読み、いよいよ長年の研究が実を結び、型システムの第一歩が踏み出されたと感じたので、その内容を自分なりに整理してみました。

Elixir 使ってみたい!! でもお仕事で使うチャンス来ないんだよね。😭


これまで動的型付け言語として愛されてきた Elixir ですが、今回のアップデート(v1.20)により、プログラムの堅牢性が一歩先へと進むことになります。


開発者の手間を増やさない型システムの導入

今回のアップデートで最も大きなポイントは、「型アノテーション(型定義の記述)を一切書かなくても、型推論と型チェックが行われる」 という点かと思います。

通常、言語に型を導入する場合、開発者が integerstring といった型を一つずつ指定していく作業が発生しがちです。しかし、Elixir v1.20 では、既存のソースコードをそのまま使いながら、バックグラウンドで型システムが動作するようになっています。

この仕組みによって見つけられるのが、公式で「検証済みバグ(Verified Bugs)」と呼ばれているものです。

検証済みバグとは?

これは、「もしこのコードが実行されたら、100% 確実にエラーになる」という種類の型違反を指します。 たとえば、数値が入るべき場所に文字列を渡している箇所などを、プログラムを実行する前にコンパイラが教えてくれるようなイメージです。

集合論的型システムというアプローチ

Elixir が採用したのは「集合論的型システム(Set-theoretic types)」という、少し珍しい手法です。これは、型を「値の集合」として捉える考え方です。

たとえば、以下のような演算を使って型を表現します。

  • 和集合 (Union): 「整数、または文字列」
  • 共通部分 (Intersection): 「A という性質と B という性質を両方持つ」
  • 否定 (Negation): 「整数ではないものすべて」

この柔軟な表現力があるおかげで、Elixir 特有のパターンマッチングや動的な挙動を、型として正確に扱えるようになっています。

型チェックの流れ

以下の図は、v1.20 における型チェックのプロセスを簡略化したものです。

flowchart TD
    A[既存の Elixir ソースコード] --> B[型アノテーションなしで読み込み]
    B --> C{型推論エンジン}
    C --> D[集合論に基づく型推論]
    D --> E{型チェック}
    E -- 矛盾を発見 --> F[検証済みバグとして報告]
    E -- 矛盾なし --> G[コンパイル継続]
    F --> H[開発者が事前に修正可能]

dynamic() 型の役割:他の言語との違い

漸進的型付け(Gradual Typing)を採用している他の言語(TypeScript や Python など)では、よく any という型が使われます。しかし、any を使うと、型チェックがその時点で「諦めてしまう」ことが多いのが実情です。

Elixir の dynamic() 型は、それらとは少し性質が異なります。

特徴 一般的な any Elixir の dynamic()
チェックの継続 any が指定されると以降のチェックをスキップしがち dynamic() であっても可能な限り型を絞り込む(ナローイング)
バグの検出力 型が不明な箇所でのエラーを見逃しやすい 明らかな矛盾があれば dynamic() であっても警告を出す
誤検知の少なさ アノテーションの不足により誤検知が起きることがある 非常に低い誤検知率(極めて正確)を目指して設計されている

たとえば、ある変数が「整数か文字列のどちらか(dynamic())」であったとしても、その変数を「リスト専用の関数」に渡そうとすれば、Elixir の型システムは「それはおかしい」と指摘してくれます。

実力を証明するベンチマーク結果

今回の実装の正確さを裏付けるものとして、「If T: Benchmark for Type Narrowing」というベンチマークの結果が紹介されていました。

これは、プログラム内の条件分岐などから、どれだけ正確に型情報を復元できるかを測るテストです。Elixir は 13 カテゴリのうち 12 カテゴリで合格しており、これは既存の動的なプログラムから「型」を抽出する能力が極めて高いことを示しています。

まとめ:これからの Elixir 開発

今回の v1.20 リリースは、型システムの完成形ではなく、あくまで「最初のマイルストーン」とのことです。

  1. まずはアノテーションなしで恩恵を受ける: 既存のプロジェクトに導入するだけで、隠れたバグが見つかるかもしれません。
  2. 低いオーバーヘッド: 開発者が型定義に追われることなく、これまで通りのスピードで開発を続けられます。
  3. 確実なエラー報告: 「かもしれない」という曖昧な警告ではなく、「確実に壊れる」箇所を教えてくれるので、修正の優先順位が立てやすいかと思います。

実際に自分のプロジェクトで試してみると、思わぬ場所でデッドコード(実行されることのないコード)が見つかったりして、コードの整理に役立つかもしれませんね。

フランスの CNRS や Remote 社など、複数の組織のパートナーシップによってこの壮大なプロジェクトが進められている点も、Elixir コミュニティの層の厚さを感じさせます。

参照記事