Lispに憧れるHaskell開発者がLanguage Serverを試す
A curmudgeon tries a language server

10年前と同じ方法でコードを書いてきた筆者が、LispのREPLでの開発スタイルに憧れつつ、Haskellで似たような体験を実現しようと試みる。ghcidとforeign-storeを組み合わせてプロセス状態を維持したまま自動リコンパイル・再起動する手法や、EmacsのEglotとHaskell Language Serverのセットアップの詳細を、実際のプロジェクトで検証する。
Lispプログラマーは、コードをREPLに直接入力して、実行中のシステムの一部を追加、削除、置換する。
HNでの議論
67- dieggsy
Common Lisp開発者として、冒頭のLispについての説明は、まあ大体(?)当たっていると思う。
私の経験では、実際にコードを「コンパイルして実行」していると言えるが、説明されているワークフローのおかげで、それを段階的に、より少ないコンテキストスイッチで行えるだけだ。しかし、実際にはコンパイルと実行が別々のステップであることもよくある。ただ、それがプログラム全体のレベルではないだけだ(例えば、関数をコンパイルして、それを呼び出す関数を実行する、など)。
また、実際の実行中にコードを再定義することがどれほど強みとして示されることが多いかに関わらず、それはそれほど一般的ではないと思う。確かに、時々行われるが、多くのプログラムはそもそもそのパラダイムに当てはまらない。例えば、一部のゲームや長時間稼働するサーバーではうまく機能するかもしれない。
ソースコードなしでイメージ内で作業することに関しては、これはひどいアイデアのように思える。些細な一回限りの実験では行うかもしれないが、一般的にはコードを早い段階で書き出して整理することの方が有益だ。説明されているように、イメージからソースコードを書き出す特に簡単でクリーンな方法があるかどうか、私は知らない。それは可能かもしれないが、私が思いつく方法はどれも、何よりも面倒で混乱するものに聞こえる。ただ私の経験がそうなのか、あるいは商用Lispの何か素晴らしい機能を見逃しているのかもしれない。
- cassepipe
まったく同じではないが、C/C++プログラマーに言及する価値がある:gdbは実際にCとC++のための一種の「安価な」ライブ環境として機能できる。
ブレークポイントで停止すると、C/C++の式を評価し、状態を変更し、関数を呼び出し、さらにcompile codeコマンドを使えば、GDBが実行中のプロセスのコンテキストで新しいC/C++コードをコンパイルして実行させることができる:
(gdb) set variable state->counter = 42
(gdb) call recompute_state(state)
(gdb) compile code
> printf("counter = %d\n", state->counter);
> do_something(state);
> end
これにより、驚くほど素晴らしい「実行中のCプログラムに接続されたREPL」体験が得られる。ヒープをいじったり、変数を変更したり、既存のコードを呼び出したり、プロセスを再起動せずに新しいコードの小さな断片を注入したりできる。
私が懐かしく思う使用例の一つは、異なるツリー構造を実装し、ツリーを.dot形式で出力するprint_dot関数を追加したことだ。gdb内からその関数を呼び出すたびに、xdotウィンドウが更新されたツリーグラフで再描画された。
これはLispイメージのように注入されたコードが永続化されるのとは本当に同じではないが、それでも持っていると便利だ。
追記:gdbのtuiを初めて試す場合、プログラムにまだprintf文がたくさんあるなら、Ctrl+Lまたはrefreshコマンドでprintf出力後の画面を整理できる。
- PaulHoule
なんてこった、そのイメージベースのプログラミングアプローチは、ひどい混乱を生むから決して主流になったことはない。
Pythonで作業するデータサイエンティストが作る悪夢のようなノートブックを見てごらん。彼らは自分の答えを、人に見せられるノートブックに焼き付けたいと思っていて、コードとデータをバージョン管理で分離し、毎回上から下まで実行できるスクリプトを持つ必要があることに気づいていない。スキルを実用的なものにしたいならね。
- ux266478
正直に言うと、GHCの構造破壊の量を考えると、イメージベースの開発は本当に悪いアイデアに聞こえる。Haskellはシステムの観点から理解するのが非常に奇妙で直感的でない言語だ。なぜなら、直接見たり操作したりしない言語のためのマクロを書くことに制限されているかのようだからだ。ソースコードからコンパイラが出力するものへの変換は、カスタム書き換えルールを導入し始める前から、非常に非局所的で予測不可能なものになり得る。
私にとって、Haskellを賢く使う方法は、反復の正反対だと思う。紙の上で解決し、洗練させ、代数的規則を見つけ、さらに洗練させ、そして自分が何をしているのか正確にわかったらコードを書き始める。
「ただコードを書き始める」という誘惑に負けると、不透明な型スパゲッティになると思う。これは私の個人的な感想だ。
- airza
この投稿からHaskellとLispについていくつか興味深い事実を学んだ。それらの事実は、どちらかを使ってソフトウェアを開発しようとするのを、悲鳴を上げて逃げ出したくさせる。Haskellに費やした時間は私をより良いプログラマーにしてくれたし、LLMがドキュメントの一部をより理解しやすくしてくれただろうが...。