**型システムはリークする抽象化です:`Map.take!/2` のケース**

- 関数 `Map.take!/2` は、第二引数で指定されたキーだけを含むマップを返すように設計されています。  
- 入力マップに存在しないキーが要求されると、`Map.take!/2` はエラーを発生させます(欠落したキーを黙って無視するのではなく)。  
  - この挙動は実装詳細を漏らすものであり、呼び出し側は例外が起こり得ることを知り、それに対処する必要があります。  
- 一方でノンバング版 `Map.take/2` は利用可能なキーだけを持つ新しいマップを返すため、多くのシナリオで安全に使えるようになっています。

**含意**

- `Map.take!/2` をパターンマッチや型推論に頼る型システムは、呼び出し側が例外を考慮していない場合、安全性を保証できなくなる恐れがあります。  
- 開発者は、バング版のエラー投げ動作が明示的に必要でない限り、`Map.take/2` の使用を優先すべきです。

2026/03/12 6:13

**型システムはリークする抽象化です:`Map.take!/2` のケース** - 関数 `Map.take!/2` は、第二引数で指定されたキーだけを含むマップを返すように設計されています。 - 入力マップに存在しないキーが要求されると、`Map.take!/2` はエラーを発生させます(欠落したキーを黙って無視するのではなく)。 - この挙動は実装詳細を漏らすものであり、呼び出し側は例外が起こり得ることを知り、それに対処する必要があります。 - 一方でノンバング版 `Map.take/2` は利用可能なキーだけを持つ新しいマップを返すため、多くのシナリオで安全に使えるようになっています。 **含意** - `Map.take!/2` をパターンマッチや型推論に頼る型システムは、呼び出し側が例外を考慮していない場合、安全性を保証できなくなる恐れがあります。 - 開発者は、バング版のエラー投げ動作が明示的に必要でない限り、`Map.take/2` の使用を優先すべきです。

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

José Valim は 2026 年 3 月 3 日に Elixir に集合論的型システムを追加することについて書きました。彼は

Map.take!/2
を例として示し、これはマップから要求されたキーが欠けている場合にエラーを発生させる関数です。

def take!(map, keys) when is_map(map) and is_list(keys) do
  Map.new(keys, fn key -> {key, Map.fetch!(map, key)} end)
end

汎用型シグネチャ

map(), [term()] -> map()
は、結果が入力キーの部分集合を含むことを表現できません。TypeScript のような静的型付き言語では、この関係はジェネリクスと
keyof
でキャプチャされます。

function take<T extends Record<string, any>, K extends keyof T>(
  obj: T,
  keys: readonly K[]
): Pick<T, K> { … }

キーのリストが実行時に決定される場合(例:

Math.random()
を通じて)、Elixir は
string[]
のような型を推論し、安全性保証を破ります。
as const
を使用するとリテラル型を保持できますが、
"name" | "email" | "age"
などの不整合なユニオンを生成する可能性があります。分配的条件付き型パターン(
TakeResult<T, Keys>
)は特定の場合で安全性を改善しますが、複雑さも増します。

Valim は二つの実用的な道筋を提案しています:

  1. 高度なジェネリクス – Elixir の推論に TypeScript スタイルの条件付き型を拡張し、部分集合関係を保持する。
  2. マクロベースの検証
    Map.take!(user, [:name, :age])
    のようにキーリストがコンパイル時リテラルであることを保証。マクロは明示的なマップ式に展開し、複雑な推論を回避します。

記事ではトレードオフを強調しています:より豊富な型システムは表現力を高めますが、学習曲線とツールのオーバーヘッドも増加します。マクロソリューションはその独自の長所と短所を持つ、簡易的な回避策として提供されています。

本文

ジョゼ・ヴァリム – 2026年3月3日


動的言語に型システムを追加する

動的言語へ型システムを導入することは、型が表現力をどのように制限するかを示す優れた演習です。
この記事では、Elixir 標準ライブラリに潜在的に存在しうる

Map.take!/2
関数を例に取り上げて、その課題と解決策を探ります。

Dashbit ではスタートアップや企業が Elixir チームを採用・育成するのを支援しています。Elixir、Nx、Livebook の創設者として、集合論的型システムを Elixir に導入する取り組みをリードしています。限られたクライアントとの経験からエコシステムを改善し続けています。私たちのチームがどのように Elixir の活用を次のレベルへ引き上げるか、ぜひお問い合わせください。


Map.take/2
を探る

Elixir ではマップが主要なキー–バリュー構造です。キーがアトムである場合、フィールドは事前にすべて分かっている「レコード」のように振る舞います。

Elixir にはすでに

Map.take/2
が存在します:

iex> user = %{id: 1, name: "Alice", email: "alice@example.com", age: 30}
iex> Map.take(user, [:name, :email])
%{name: "Alice", email: "alice@example.com"}

キーが存在しない場合は無視されます。マップをレコードとして扱う際には、キーが必ず存在することを保証したいケースが多く、そこで

Map.take!/2
の提案が生まれました。


Map.take!/2
の提案

最近、Wojtek Mach が

Map.take!/2
を追加することを提案しました。Elixir では感嘆符付き関数は「入力が有効でも例外を投げる可能性がある」ことを示します。例えば:

iex> Map.take!(user, [:name, :email, :missing])
** (KeyError) unknown key :missing

単純な実装は次のようになります:

def take!(map, keys) when is_map(map) and is_list(keys) do
  Map.new(keys, fn key -> {key, Map.fetch!(map, key)} end)
end

型システムを導入すると、戻り値の正確な形状を反映した署名が必要になります。


現在(広すぎる)型署名

現段階では最も適切とできるものは次のようになります:

$ map(), [term()] -> map()
def take!(map, keys) when is_map(map) and is_list(keys)

これは戻り値が

map()
であることだけを示し、キーについては情報を持ちません。そのため結果を安全に利用することができません。


静的型付き言語の難点

多くの静的型付け言語では、キーごとの組み合わせごとにボイラープレートを書く必要があります:

def take_name_and_email(user) do
  %{name: user.name, email: user.email}
end

def take_name_and_age(user) do
  %{name: user.name, age: user.age}
end

Map.take!/2
の目的はこのようなボイラープレートを回避することです。


TypeScript の
keyof

TypeScript における類似例が課題を示します:

function take<T extends Record<string, any>, K extends keyof T>(
  obj: T,
  keys: readonly K[]
): Pick<T, K> { /* ... */ }

キーリストが静的に既知であれば機能します。しかし、ランタイムで変化する(例えば

Math.random()
によって選択される)場合は型推論が
string[]
へと崩れ、静的チェックが失われます。

as const
を使った精度強制やキーをマッピングすると、不整合が生じる可能性があります。推論された型が実際に存在しないフィールドを許容してしまう恐れがあります。


安全性への道

Ken AKAFrosty は分配的条件型アプローチを提案しました:

type TakeResult<T, Keys extends readonly (keyof T)[]> =
  Keys extends any ? Pick<T, Keys[number]> : never;

function take<
  T extends Record<string, any>,
  K extends keyof T,
  const Keys extends readonly K[]
>(obj: T, keys: Keys): TakeResult<T, Keys> { /* ... */ }

キーリストが文字列リテラルのユニオンである場合、これは安全性を保ちます。ただし、キー配列上でマッピングするような複雑な変換では破綻する可能性があります。


マクロによる逃げ道

一つの解決策は

Map.take!/2
をマクロにすることです。コンパイル時に展開すると:

Map.take!(user, [:name, :age])   # => %{name: user.name, age: user.age}

マクロはキーリストがリテラルであることを保証でき、複雑な署名を必要とせずに正確な結果型を推論できます。

マクロは他言語(Racket、Elixir の

printf
例など)でも成功裏に利用されています。静的型だけでは保証できないコンパイル時制約を課すことが可能です。


要点

動的コードは表現力豊かで正しくても、静的型システムの検証が難しい場合があります。ロジックをリファクタリングしたりカプセル化したりすると、意図せず型安全性が損なわれることがあります。そのためには:

  • より多くのボイラープレートを許容する
  • 高度な型抽象(コストが高い)を追加する
  • あるいはマクロでコンパイル時保証を実装する

という選択肢があります。既存の動的言語に型システムを設計・導入する際には、これらのトレードオフを理解しておくことが不可欠です。

同じ日のほかのニュース

一覧に戻る →

2026/03/16 4:12

「Chrome DevTools MCP」 (原文と同じく略語をそのまま使用します)

## Japanese Translation: **改訂要約** Chrome の MCP(Machine‑Code Processor)サーバーは、現在実行中の Chrome セッションに直接コーディングエージェントを接続できるようになり、新しいインスタンスを毎回起動する必要がなくなりました。 この機能を利用するには、`chrome://inspect#remote-debugging` でリモートデバッグを有効化し、MCP サーバーを `--autoConnect` フラグ付きで起動します(例:`gemini-cli --autoConnect --channel=beta`)。 エージェントがセッションを要求すると、Chrome は許可ダイアログを表示し、「Chrome is being controlled by automated test software」というバナーを表示します。エージェントはそのアクティブなセッションに対して Network や Elements などの DevTools パネルへアクセスできます。 MCP サーバーは依然として元々の起動方法をサポートしています:ユーザープロファイルの指定、リモートデバッグポート経由での接続、または隔離された一時プロファイルの実行。 サンプルワークフローは次のとおりです。リモートデバッグを有効化した後、エージェントプロンプトに「Check the performance of https://developers.chrome.com」と入力すると、MCP サーバーが接続し、ページを開き、パフォーマンストレースを取得します。 Chrome M144(Beta)で利用可能なこの機能は、デベロッパーが新しいセッションを開くことなく手動の DevTools 使用と AI 支援デバッグをシームレスに切り替えられるようにし、将来的に MCP を通じてコーディングエージェントへより多くの DevTools パネルデータを段階的に公開する基盤を整備します。

2026/03/16 6:22

カナダの法案 C‑22 は、カナダ国民への大量メタデータ監視を義務付けています。

## Japanese Translation: > Bill C‑22(Lawful Access Act)は、通信事業者および電子サービスプロバイダー(ESP)への法執行アクセスを拡大すると同時に、一部のプライバシー制限を強化します。従来のBill C‑2で広範な無証拠要求が認められていた点を置き換え、通信事業者に対しては「サービス確認」権限のみを限定的に付与します。他の加入者情報については、合理的根拠基準に基づく裁判所承認命令が必要となります。 > > 本法ではまた、Supporting Authorized Access to Information Act(SAAIA)も導入されます。この条項はBill C‑2の多くの要件を反映しつつ、GoogleやMetaなどのESPにも適用します。ESPはデバイス・機能テストへの協力、要求の秘密保持、および「コアプロバイダー」として指定される可能性があります。コアプロバイダーは、データ抽出ツールの開発・テスト・維持管理、監視装置の設置、当局への機能通知、そして特定メタデータ(例:送信ログ)を最大1年間保持する義務があります。ただし、**送信内容、ウェブ閲覧履歴、またはソーシャルメディア活動の保持を強制されることはありません**—この例外はシステム的脆弱性への対処に限定されています。 > > 監督はインテリジェンス・コミッショナーが承認した省令によって行われますが、多くの詳細は機密扱いとなっています。本法は、ブダペスト条約第二追加議定書や米国のCLOUD Actなどとの国際情報共有協力を改善することを目的としていますが、重大な市民権利懸念を提起し、通信事業者およびESPに大きなコンプライアンス負担を課す可能性があります。結果として、ユーザーの監視リスクが高まる恐れがあります。

2026/03/16 4:25

49 MB のウェブページ

## Japanese Translation: 記事は、現代のニュースサイトがデータ量の多いリクエストや侵入的な広告、トラッキングスクリプトで読者を過剰に負荷させていると主張し、滑らかな閲覧体験よりも収益を優先していることを指摘しています。 - **具体的証拠:** ニューヨーク・タイムズの記事1件が422のネットワークリクエスト、49 MBのデータを生成し、安定するまでに2分かかったと報告されています。2006年には同じページは1.5 Mbpsの接続で数分間停止していた(10曲分のMP3音源に相当)。 - **広告インフラ:** クライアント側のプログレマティックオークションがRubicon ProjectやAmazon Ad Systemsなどのエクスチェンジへ何十もの同時入札リクエストを送信し、膨大なJavaScript解析を要求します。 - **トラッキングペイロード:** 約5 MBのトラッキングスクリプトがPOSTビーコンをファーストパーティー端点(例: a.et.nytimes.com/track)やクロスサイトトラッカー(doubleclick.net、casalemedia)へ送信し、バックグラウンドでユーザー識別情報を構築します。IABの「purr」同意エンドポイントはページロード直後にこれらのスクリプトを即座に起動させるため、クッキーバナーはプライバシー保護ではなく法的シールドであることが示されています。 - **UX戦術:** パブリッシャーはCPMやビューアビリティ指標を読者体験よりも重視し、モーダルポップアップ、低コントラストの閉じアイコン、強制スクロール、自動再生のスティッキービデオ(CPU熱、バッテリー消費、Fitts法違反)や「Read More」ボタンで記事を切り捨て、追加広告をロードします。これらは広告iframeが遷移後に読み込まれる際にレイアウトシフト(CLS)を引き起こし、Google Core Web Vitalsの指標による離脱率を高めます。 - **モバイル問題:** モバイルニュースサイトはコンテンツに約11 %しかビューポートを割り当てず、狭いスリット状の表示領域がインタラクションコストを増大させます。 - **緩和策:** 非必須オーバーレイはスクロール深度≥50 %または60 秒滞在後に遅延し、モーダルキューを順序付け、アクセシブルで低侵襲のモーダルを使用し、非同期コンテンツ用スペースを確保してCLSを回避します。 - **代替案:** text.npr.org、lite.cnn.com、およびRSSフィードといった軽量フォーマットは、読者が余計な要素のないプライバシーフレンドリーなニュース消費を好むことを示し、広告中心のUIパラダイムに挑戦します。 **結果:** このまとめはすべての主要ポイントを完全に反映し、説明のない推測を避け、記事の主張を明確で読者フレンドリーな概要として提示しています。

**型システムはリークする抽象化です:`Map.take!/2` のケース** - 関数 `Map.take!/2` は、第二引数で指定されたキーだけを含むマップを返すように設計されています。 - 入力マップに存在しないキーが要求されると、`Map.take!/2` はエラーを発生させます(欠落したキーを黙って無視するのではなく)。 - この挙動は実装詳細を漏らすものであり、呼び出し側は例外が起こり得ることを知り、それに対処する必要があります。 - 一方でノンバング版 `Map.take/2` は利用可能なキーだけを持つ新しいマップを返すため、多くのシナリオで安全に使えるようになっています。 **含意** - `Map.take!/2` をパターンマッチや型推論に頼る型システムは、呼び出し側が例外を考慮していない場合、安全性を保証できなくなる恐れがあります。 - 開発者は、バング版のエラー投げ動作が明示的に必要でない限り、`Map.take/2` の使用を優先すべきです。 | そっか~ニュース