recipe-collection
recipe-collection copied to clipboard
コンテンツ中の haskell コードを自動でコンパイルする。
仕組みとしては、Travis-CIとかを使えばいいのかもしれませんね。
工夫のしどころはコンテンツを
- Markdownファイル(foo.md)として書いて、そこにコードブロックを埋め込む
- Haskellスクリプトファイル(foo.hsまたはfoo.lhs)として書いて、説明はコメントとして埋め込む のどちらにするかで考え方が違ってくると思います。
基本的には、1. の場合は解説が主で、コードは説明のための具体例、2. の場合はコードが主で、解説はコメントと考えることになります。
そのうえで、1. の場合は、コードの抽出と抽出したコードの実行の仕組みに工夫がいりそうですね。2. の場合は、文書としてはHaddockで処理してHTMLでみる程度でよければ全体をパッケージにするとそのまま利用可能なので結構便利かも。
TFwHのサイト はTravis-CIとは未連携で未完成ですが 2.の考え方でサイトを構成しています。 自動コンパイルの仕組みは設定していませんが、master はHaskellスクリプトで構成しておいて gh-pagesをstack haddockで生成したhtmlで構成するようにしてます。 tfwhパッケージ はパッケージとしての汎用性はないですが、 コードはすぐに試せるようになってます。
@nobsun コメントありがとうございます。
仕組みとしては、Travis-CIとかを使えばいいのかもしれませんね。
そうですね。 それができればバッヂも使えるのでサンプルコードの健全性はひと目でわかるようにできそうです。 Haskell で ci ツールを回したことはありませんけど、依存パッケージを大量に使ってたりしても大丈夫なのかな?
基本的には、1. の場合は解説が主で、コードは説明のための具体例、2. の場合はコードが主で、解説はコメントと考えることになります。
このレシピ集では、メンテナビリティを重要な視点として考えています。 いってみればコンテンツを陳腐化させない、というのがミッションですね。 そのために、編集コストはできるだけ下げたいですし、閲覧者が気付いたらすぐにツッコミいれれるような仕組みにもっていきたいです。
いま、1. の方針ではじめているのはそういう背景にもとづいています。 markdown だと前提知識は(haskell や haddock に比べて)少なくて済みますし、github 上でいきなりコンテンツになっている、という手軽さを活用しようとしています。
とはいえ、パッケージにする、という発想はなかったので面白いですね。
コンテンツは markdown のまま何とかしてパッケージにする、というのはさすがにムリでしょうか?
コンテンツは markdown のまま何とかしてパッケージにする、というのはさすがにムリでしょうか?
markdown から有効なコードブロックだけを抽出して、モジュールファイルに変換するツールがあれば、 masterブランチのリポジトリを処理してcodeブランチ(名前は適当)を構成する仕組みが作れそう。
自動化の具体的な方法はよく判っていないですがなんとかなるかも。
markdown から有効なコードブロックだけを抽出して、モジュールファイルに変換するツールがあれば、 masterブランチのリポジトリを処理してcodeブランチ(名前は適当)を構成する仕組みが作れそう。
おお、それができればやりたいですね!
markdown から有効なコードブロックだけを抽出して、モジュールファイルに変換するツール
これには https://hackage.haskell.org/package/markdown-unlit というパッケージがあります。ただしdoctestのようにghciのセッションとしてテストする機能はないので、必要であれば自作する必要があります。
markdownからコードブロックを抽出できるライブラリがあるのであれば、
-
src/template/article0001.md
- 記事本文
-
app/Article.hs
- Hakyllなどを使って実際の記事を生成
-
src/Codes/Article0001.hs
-
article0001.md
内のコードをTHで展開してコンパイルできるようにする - 記事ごとにファイルを用意することで、記事ごとに依存ライブラリが異なる問題や、関数名の衝突を防げる
-
-
app/Code.hs
-
src/Codes/*.hs
をよみこむ
-
みたいにすれば、記事の生成(app/Article.hs
)とコードが正しいかどうかのチェック(app/Code.hs
がコンパイルできるかどうか Travisとかでチェック)が同時にできそうですね!
main
関数をコードブロックで定義することも想定するとTHで展開した結果に対してエラーがでないように、
THで展開する際に適当にmain
をmain0
などにリネームすることも必要だと思います。
実際には人力でコードをチェックしたほうが結果的にはコストが低いとは思いますが、 このプロジェクト自体がHaskellの魅力を体現することになるのであれば、こういう仕組みを導入してもいいかもしれないですね!
REPLの実行例が書いてあるmarkdownについて似たようなことやったんですが、そのときは、
https://github.com/sol/doctest/blob/master/ghci-wrapper/src/Language/Haskell/GhciWrapper.hs
をコピペしてきて使いました(publicじゃないので)。
REPLじゃない通常のsnippetはファイルに切り出して :l
で読ませました。こうしておくと、記事中で関数などを定義した snippet を出した後に、直後にそれを REPL から使うという解説の仕方をしている場合にも検証ができて便利でした。