
【2026年7月版】
「Roc」入門 — Elm譲りの純粋関数型言語がRustホストと組む未来
公開日: 2026/07/03
読了時間: 約 13分
はじめに
こんにちは、あそぴテックです。
前回の記事「「Nim」入門 — Cにトランスパイルするマルチパラダイム言語の現在地」では、AlopexDB の SQL パーサー移行候補として調査された Nim を紹介しました。今回は、その調査でもう一方の主役だった Roc(ロック) を取り上げます。
Roc は Elm の作者 Richard Feldman 氏が率いる、比較的新しい純粋関数型言語です。「Rust ホスト + Roc アプリケーション」という独特のアーキテクチャで、システム系の世界に関数型を持ち込もうとしています。
Roc ってどんな言語?
Roc は次のような特徴を持ちます。
- 純粋関数型 — 副作用は明示的、参照透過性が保たれる
- Hindley-Milner 型推論 — 型注釈をほとんど書かずに強い静的型付けが得られる
- ADT + パターンマッチが第一級 — Tag Union(
[Ok val, Err e]のような直和型)が言語の中心 - Perceus 参照カウント — GC はあるが停止時間なし・スケジューリング不要を目指す設計
- LLVM ネイティブへコンパイル — ネイティブバイナリを吐く
- Platform / Host モデル — システムコールや副作用は「Platform」に集約し、アプリは純粋関数として書く
言語仕様の雰囲気は Elm や Haskell にかなり近く、初見でもかなり読みやすいです。次のコードは Roc の SQL レキサー実装の一部です(alopex-db/alopex experiment/sql-parser-trial より抜粋)。
Token : [Select, From, Where, Ident Str, IntLit I64, Star, Comma, Eq]
keyword : Str, Token -> Parser Utf8 Token
keyword = |text, tag|
const(tag) |> skip(string(text))
token : Parser Utf8 Token
token = one_of([
keyword("SELECT", Select),
keyword("FROM", From),
string("*") |> map(|_| Star),
string(",") |> map(|_| Comma),
many1(alpha) |> map(|chars| Ident(Str.from_utf8(chars))),
])「関数を演算子でつないでいく」パイプライン |> と、パターン一致でトークンを組み立てる書き方は、Elm や F# を触ったことがある人なら違和感がないはずです。
2026年6月時点の現在地 — 「まだ 0.1 でもない」段階
Roc は 本当に若い言語 です。2026 年 6 月時点で見ると、以下のようなステータスになっています。
バージョン変遷
| リリース | 日付 | 備考 |
|---|---|---|
| alpha1 | 2025-01-29 | 初の alpha リリース |
| alpha2-rolling | 2025-01-29 | 大規模構文変更 |
| alpha3-rolling | 2025-02-26 | |
| alpha4-rolling | 2025-08-26 | 最新版。ビルド速度改善、新 builtins |
公式は明確に 「Roc is not ready for a 0.1 release yet」 と述べており、1.0 のタイムラインも未発表です。
alpha2 での破壊的変更(2025年1月)
alpha2 では、言語設計の見直しに伴う大規模な破壊的変更が入りました。
| 変更 | Before | After |
|---|---|---|
| 関数呼び出し | func arg | func(arg) |
| 命名規則 | camelCase | snake_case |
| エラーハンドリング | Task 型 | ! サフィックス + ? 演算子 |
| 文字列補間 | $(expr) | ${expr} |
| 論理演算子 | && / || | and / or |
| タグ構築 | Ok val | Ok(val) |
移行ツール roc format --migrate は提供されていますが、Task → ! の置き換えは手動対応が必要でした。実際に Alopex チームが SQL パーサー試験実装で計測したところ、24 箇所の手動修正 が発生しています。
alpha 段階の言語である以上、この規模の破壊的変更は今後も想定しておく必要があります。
Zig コンパイラへの書き直し
大きな話題として、Roc コンパイラの LLVM コード生成部分が Rust(約 18,000 行)から Zig(約 1,700 行)に書き直されました。
| 項目 | 内容 |
|---|---|
| 規模 | 18,000 行 Rust → 1,700 行 Zig(10 倍削減) |
| アーキテクチャ | Mono IR → Canonical IR(プレ単相化)に変更 |
| 未実装機能 | match 式、ラムダ、複雑な union、参照カウント、デバッグ情報 |
| 優先課題 | builtins 実装の完了(Issue #9596) |
Rust 版で膨らみすぎたコンパイラを、Zig の comptime を活かして根本から作り直しているというかなり大胆な判断です。ちなみに Roc の「Host(副作用担当)」は引き続き Rust で書けますし、basic-webserver は Rust の hyper + tokio がホストになっています。「コンパイラ自体を書く言語」と「アプリの Host を書く言語」を分けて考えている のは Roc らしい選択と言えるでしょう。
コミュニティ
- GitHub 5,700 stars / 387 forks / 43,653 commits
- Zulip チャットが活発
- コードベースの 92.9% が Zig
Roc のここが面白い
純粋関数型 + ADT ファースト
Roc の AST は、Elm と同じく Tag Union で自然に書けます。
SqlNode : [
Ident Str,
StrLit Str,
IntLit I64,
BoolLit Bool,
NullLit,
StarLit,
BinOp { op : BinaryOp, left : SqlNode, right : SqlNode },
UnOp { op : UnaryOp, operand : SqlNode },
FnCall { name : Str, args : List SqlNode },
ColRef { table : Str, column : Str },
SelectStmt {
columns : List SqlNode,
from : List SqlNode,
where : [Some SqlNode, None],
# ...
},
InsertStmt { table : Str, columns : List Str, values : List SqlNode },
# ...
]Rust であれば Box<SqlNode> を使い、enum の variant サイズが揃わずに #[allow(clippy::large_enum_variant)] を書きたくなるところですが、Roc は Box の概念がユーザーコードに現れません。ランタイムが自動的にヒープに載せ、Perceus 参照カウントで管理します。
Perceus 参照カウント
Roc の GC 戦略は Perceus と呼ばれる方式で、Koka 言語の研究成果を取り入れたものです。特徴は次の通りです。
- 静的解析でカウント操作の位置を決定 → 実行時のアトミック操作を最小化
- stop-the-world がない
- 手動チューニング不要
- 将来的にリニア型による “in-place update” 最適化も見据えている
Platform / Host モデル
Roc で最も特徴的なのは Platform / Host モデル です。副作用(ファイル IO、HTTP、TCP など)はすべて Platform が提供し、アプリ側(Roc コード)は「純粋関数の集合」として書きます。
代表的な Platform を挙げます。
| Platform | バージョン | 概要 |
|---|---|---|
| basic-cli | v0.20.0 (2025-08) | ファイル、HTTP、TCP、CLI 引数 |
| basic-webserver | v0.13.1 (2026-01) | Rust (hyper + tokio) バックエンドの Web サーバ |
つまり Rust で書かれた Host が、内部で Roc アプリを C ABI 経由で呼び出す 形で動作します。
Roc App (純粋関数)
↓ C ABI で export(roc_app_main 等)
Rust Host (副作用担当)
↓
OS / Network / DBこれは、後述する AlopexDB の「Rust ストレージエンジン + Roc パーサー」 構成と非常に相性が良く、「言語横断でクリーンに責任を分離できる」設計です。
コンテナ開発環境
Roc は現時点で公式 Docker イメージを提供していませんが、バイナリリリースを curl + tar で入れれば完結します。
FROM debian:bookworm-slim AS roc-env
RUN apt-get update && apt-get install -y \
curl ca-certificates gcc libc6-dev \
&& rm -rf /var/lib/apt/lists/*
ARG ROC_VERSION=alpha4-rolling
RUN curl -OL https://github.com/roc-lang/roc/releases/download/${ROC_VERSION}/roc-linux_x86_64-${ROC_VERSION}.tar.gz \
&& tar xzf roc-linux_x86_64-${ROC_VERSION}.tar.gz \
&& mv roc-linux_x86_64-${ROC_VERSION} /opt/roc \
&& rm roc-linux_x86_64-${ROC_VERSION}.tar.gz
ENV PATH="/opt/roc:${PATH}"
WORKDIR /appNix Flake での再現性重視なセットアップも可能です。
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
roc.url = "github:roc-lang/roc";
};
outputs = { nixpkgs, roc, ... }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
rocPkgs = roc.packages.${system};
in {
devShells.${system}.default = pkgs.mkShell {
buildInputs = [ rocPkgs.cli ];
};
};
}バイナリの取得さえ通れば構築コストは Nim とほぼ同等 です。差は「公式イメージがあるか」だけであって、コンテナ内では curl + tar で完了します。
ランタイム性能 — データは未公開
正直に書くと、Roc の対 Rust ベンチマークは公開データがまだ揃っていません。公式は「GC 付き主要言語(Go, C#, Java, JS)より速い」を目標に掲げていますが、Rust や Nim との定量比較は現時点で存在しません。
一方で、コード量とビルド時間についてはかなり良い数字が出ています(Alopex での試験実装、SQL パーサー現在の実装コード量)。
| 計測項目 | Roc | Rust |
|---|---|---|
| 実装コード量 | 1,049 行 | 2,964 行 |
| release ビルド | 4.7 秒 | 165 秒 |
| dev ビルド | 0.8 秒 | — |
| テスト実行のみ | 0.3 秒 | 0.01 秒 |
| SQLite 相当推定(dev) | 〜5 秒 | — |
| SQLite 相当推定(テスト実行) | 〜2 秒 | — |
release ビルドは Nim よりやや遅いのですが、dev ビルド 0.8 秒 → SQLite 相当でも 5 秒程度 という開発イテレーションの速さが Roc の大きな武器です。
Roc で運用する場合の注意点
以下は Alopex の試験実装で実際に踏んだ落とし穴です。
--linker=legacyが必須(Linux) — surgical linker の issue #3609 が未解決basic-cliの URL ハッシュが版ごとに変わる — Dockerfile のメンテコストになる- 未使用 import はコンパイルエラー(exit code 2) — 修正必須
.rocファイルの命名規則がやや厳しい — CamelCase モジュール名との整合など- API 変更の頻度が高い — 上記の 24 箇所修正はその典型
言語設計は洗練されていますが、本番採用には時期尚早 というのが現状の総合評価です。まずは PoC / 実験ブランチで先行評価する、というのが妥当な向き合い方でしょう。
Roc は「今」誰にとって魅力的か
Roc を触ってみる価値があるのは、次のような層だと感じます。
- Elm や Haskell 経験者で、システム系寄りに関数型を持ち込みたい人
- AST 定義・パーサー・純粋計算コアを、GC ありつつも安全に書きたい人
- Rust ホスト + 関数型アプリ という新しい構成に興味がある人
- 言語処理系そのものの設計(Perceus、Platform/Host、Canonical IR)を追いかけたい人
逆に、「今すぐ本番サービスを構築したい」「ライブラリエコシステムがある程度揃っていてほしい」場合は、まだ Nim・Rust・Go を選んでおいた方が確実です。
とはいえ、Zig コンパイラ書き直しが完了して 0.1 → 1.0 のロードマップが見えてきたら、「純粋関数型 × ネイティブ性能 × Rust 連携」の三拍子が揃った稀有な言語になるはずで、今のうちから追いかけておく価値は十分にある と個人的には感じています。
次回は、この Nim と Roc それぞれで実装された SQL パーサーの中身を並べて比較する 記事を書きます。次の記事「Rustは万能じゃない — 言語パーサーはNimかRocで書け」で、同じ機能を 3 言語で書くと何が見えてくるのかを解説しています。
それでは!
参考リンク
- Roc 公式サイト
- roc-lang/roc (GitHub)
- Roc Install Guide
- Roc Platforms and Apps — Platform/Host モデルの公式解説
- basic-webserver (Rust Host 実例)
- roc-parser — Parser Combinator for Roc
- Roc with Richard Feldman — Rust in Production Podcast
- alopex-db/docs — Alopex DB 調査ドキュメント
- alopex-db/alopex
experiment/sql-parser-trial