拡張可能なプログラム

Ruby のような実行時に何でもできる言語だと、ユーザが書いた Ruby のコードを実行したり、プラグインの gem をインストールするだけで使えるようになったりする仕組みを提供できる。 例えば spring は ~/.spring.rb や config/spring.rb を自動的に読み込み、また spring-commands- で始まる gem を自動的に require し、プラグイン側は Spring.register_command で独自のコマンドを定義できるようになっている。

pry も似たようなかんじで、~/.pryrc や ./pryrc を読み込んだり、pry- で始まる gem を自動的に require して、プラグイン側は Pry.commands.import 等で独自のコマンドを定義できるようになっている。

一方、Haskell のような言語だとこういうことをするのは難しい。 Haskell で書かれていて Haskell で拡張可能なプログラムというと XMonad くらいしか思い付かないんだけど、XMonad は「拡張可能なウィンドウマネージャ」というより「ウィンドウマネージャを簡単に作れるライブラリ」に近くて、実際 XMonad の設定は main 関数を持つ普通のプログラムとして書かれる。

XMonad の場合、設定をコンパイルして得たバイナリは ~/.xmonad/xmonad-$arch-$os に作られるんだけど、xmonad コマンドは ~/.xmonad/xmonad-$arch-$os を exec し、それに失敗したらデフォルトの設定で xmonad をスタートするラッパーの役割しか持っていない。

Haskell で拡張可能なプログラムとして yi を忘れてた。 yi も XMonad と同じ方式で、設定ファイルは main 関数を持つ普通のプログラムとして書かれるっぽい。XMonad 方式の設定を実現するための dyre というライブラリがあり、yi はこれを使っている。

Haskell で拡張可能なプログラムを書くとしたら、XMonad のようなアーキテクチャにするのがいいのかもしれない。 pandoc は内部では新しい Reader / Writer を追加できるようなアーキテクチャになってるけど、ユーザ側が好きな Reader / Writer を追加できるようなものではなさそう。