作成: 2018-06-08T20:06:33+09:00

HaskellでDebug.Traceする時に変数名を2回書かなくても良くなるライブラリdebug-trace-varを公開しました

ncaq/debug-trace-var: You do not have to write variable names twice in Debug.Trace

秒速でコピペしたいHaskellデバッグ用関数 - Qiita を読んで, そう言えばprintデバッグする時に色々と面倒だから開発したかったことを思い出したので, 昼休みに書きました.

printデバッグする時には, どの変数をデバックしているのかわかりやすいように, しばしば以下のように書きます.

import Debug.Trace main :: IO () main = do let a = 1 traceIO $ "a = " ++ show a

これは変数名を2回書いて面倒くさいし可読性が悪いです.

なのでQuasiQuotesによって2回書かなくても済むようなライブラリを書きました.

{-# LANGUAGE QuasiQuotes #-} import Debug.Trace.Var main :: IO () main = do let a = 1 [ traceVarIO | a | ]

実装 C++なら評価前の変数名取得はプリプロセッサでやるでしょうし, Haskellでもプリプロセッサで実装出来るのかもしれませんが, プリプロセッサのマクロだと import 関係や関数の構造が後でわからなくなるので言語標準の方法で書きました. これまでTemplate Haskellを使う側ではなくライブラリ作成のために使ったことが無かったので, 一度使ってみたかったという感情もありました. 実装は単純で, 左辺に準クオートされた文字列を置いて, 右辺に lookupValueName で変数を取得して ushow して置いているだけです. ushow というのはunicode-show :: Stackage Serverの関数で, 日本語などのマルチバイト文字も数値にしないで show してくれます. 名前クオートはトップレベルではないと使えないとか, 引数で渡されてきた Exp は実行できないとか, 様々な学びがありました.

懸念点 Template Haskellの構文木を直接使っているのでアップデートしたら破壊されそう. Template Haskell初心者なので今ひとつ良い方法が思いつきませんでした.

出来なかったこと 変数だけではなく複雑な式も評価したかったのですが, 方法がわかりませんでした. String として渡された式を構文木にする方法がわからない.

もっと真面目にやるなら 構造的なログを作って, そこに日時やスタック情報を入れて, 構造的ファイルに出力して, コンソールに出力するものだけ a = 1 のような形にしたい. そして検索などを簡単に出来るようにしたい. 要はsystemdのjournaldみたいなことをやりたいですね.