
2026/01/24 5:07
アローはアローへ、カテゴリはクエリへ
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Catlang は、単一の PostgreSQL
SELECT 文に直接コンパイルされる小さなカテゴリ論的プログラミング言語です。そのコアプリミティブは矢印(関数)と合成、分岐(
△)、共積注入(inl、inr)、除去(▽)などのカテゴリー演算です。中間言語(IL)はスタックベースで、変数名の代わりに射影(prj₁、prj₂)を使用し、変数自体が存在しないため、バックエンドコンパイルが簡素化されます。
特殊なループプリミティブ
cochoice は、Either 値上の矢印を通常の反復に変換します;コンパイラはこれを再帰的共通テーブル式(CTE)として実装します。PostgreSQL 17 に明示的なステップカウンタがないため、実装では clock_timestamp() を使用して行を順序付け、最終結果を選択します。
SQL 生成は各カテゴリー演算を SQL 構造にマッピングします:合成 → ネストされたクエリ、分岐 →
CROSS JOIN、共積 → アクティブなコンストラクタを示す列が NOT NULL とマークされた三列テーブル、除去(▽)→ UNION ALL で非 NULL 列をフィルタリングします。
簡単な例プログラムは左値が生成されるまでループし、
100 を返します。PostgreSQL 17 で生成されたクエリを実行すると、その単一行が得られます;LIMIT 1 節を削除すると各反復ごとに1行が表示され、ループのトレースが明らかになります。
すべてのソースコードは GitHub にあり、Template‑Haskell バックエンドは同等の Haskell 矢印コードを生成できます。著者は Brainfuck インタプリタなどのより複雑なプログラムを SQL にコンパイルする予定であり、PostgreSQL をその内部で実行するといったメタ・サーキュラーアイデアも検討しています。
この改訂された概要は、すべての主要ポイントを完全に反映し、非推奨の推論を回避し、曖昧な表現を明確化しています。
Text to translate
(incorporating missing points and removing unsupported inferences):**
本文
最近、少し休暇を取っており、特に自分らしい不合理な使い方で時間を過ごしています。
その結果として、SQL にコンパイルされる小さなプログラミング言語「catlang」を作りました。
これは新しいクエリ言語ではなく、プログラミング言語であり、コンパイラは 1 つの巨大な
SELECT 文を出力します。そのクエリを PostgreSQL で実行すると、あなたのプログラムの結果が得られます。
なぜこんなことをしたのでしょうか?
面白いコンパイル先を使って言語自体の機能を試したかったからです。中間表現は抽象的なカテゴリー理論の雑学で構成されており、後ほど詳しく説明しますが、まずは実際に動作させてみましょう。
簡単な例
以下は入力に関係なく
100 を返す関数ですが、その処理を while ループと同等の形で書いています。
count :: Int -> Int count = x -> loop x i -> n <- join id id -< i z <- abs . (-) -< (n, 100) case z of inl _ -> inr . (+) -< (n, 1) inr _ -> inl -< n
アロー記法に慣れていれば、ブロックは単一の
proc ブロックと見なせます。アイデアは、
x から始めてそれをループし、新しい値 n を計算し、それから 100 を引いて絶対値を取るというものです。結果が負(inl)なら n に 1 を足して inr で包み、ループは「この新しい値で再度実行する」と解釈します。そうでなければ (inr) は n を返します。
中間言語
count のソース構文をデスギャラリングした後、変数名のないアローとコンビネータだけからなる IL 表現が得られます:
id △ id ⨟ cochoice ( undist ⨟ ( (prj₁ ⨟ id ▽ id) △ id ⨟ ( prj₁ △ 100 ⨟ (-) ⨟ abs ) △ id ⨟ prj₁ △ id ⨟ dist ⨟ ( (prj₂ ⨟ prj₂ ⨟ prj₁) △ 1 ⨟ (+) ⨟ inr ) ▽ ( prj₂ ⨟ prj₂ ⨟ prj₁ ⨟ inl ) ) △ prj₂ ⨟ dist
IL は読むのが意図的に難しく設計されていますが、各コンビネータには SQL にマップできる明確な意味があります。
カテゴリ理論の基礎
– 恒等アロー(何もしない)。id- 合成
– 2 本のアローを接続。(⨟) - フォーク
– 入力を受け取り、ペアで出力。(△) - 投影
,prj₁
– ペアから要素を抽出。prj₂ - コプロダクトは
,inl
を注入に使い、分岐にはinr
を使用。(▽)
ループは cochoice で実装されます:
cochoice :: (Either a c ~> Either b c) -> (a ~> b)
これはアローを
Either 上で走らせ、inl が出るまで継続し、それ以外の場合は inr の値をフィードバックします。これにより純粋で静的型付けされたループ構造が得られます。
SQL へのコンパイル
各コンビネータは次のような SQL フラグメントへ変換されます:
| コンビネータ | SQL 変換 |
|---|---|
| |
| ネストされたクエリ |
| (列を結合) |
/ | に を付けて実装 |
| 再帰 CTE () でループし、 が出たら停止 |
積(product)は別々の列として表現され、コプロダクトは 3 列にフラット化されます:
(f1 INT NOT NULL, f2 INT, -- f2 と f3 のどちらか一方のみが NOT NULL f3 INT)
再帰 CTE はタイムスタンプ列 (
clock_timestamp()) を使ってイテレーションを順序付け、最終行を選択します。
生成された SQL
count に対する上記の変換を実行すると、大量のクエリが生成され、PostgreSQL 17 で実行すると 100 を返す単一行が得られます。最後の行を次のように変更すると:
SELECT * FROM recursion ORDER BY step DESC LIMIT 1)
から
SELECT * FROM recursion ORDER BY step DESC)
に変えると、全ての中間イテレーションが表示されることが確認できます。
今後の方向性
- brainfuck インタプリタを catlang で書き、文字列操作プリミティブを追加して SQL にコンパイル。
- 他のバックエンド(例:C や PostgreSQL 内の PostgreSQL)への展開を検討。
このプロジェクトは Haskell のアロー記法と「Compiling to Categories」という論文からインスピレーションを得ています。ソースコードは GitHub に公開しており、改善提案(プルリクエスト)は歓迎です。
主要用語
– catlang で書けるアロー。~>
– メタ理論における通常の関数。->