Old/sampou.org/Trace

Trace


Debug.Trace を使う

nobsun(2007/07/04 10:53:31 JST)

Haskellでもprintfデバッグのようなことをしたいことがある.このとき Debug.Trace モジュールにある trace という関数が便利である.

trace :: String -> a -> a

この関数は値としては第二引数をそのまま返す関数なのだが,その値が評価さ れたときにコンソールに第一引数で与えた文字列を表示するというののである.

たとえば,

add :: Int -> Int -> Int
add x y = trace "'add' called" (x + y)

と定義して add 1 (2*3) を評価すると

*Main> 1 + add 2 (3*4)
'add' called
15

となる.

ジョイントにながれるデータを見る

Haskellのプログラミングでは関数適用オペレーター($)を明示的につかって, 処理の連結をおこなうことが良くある.すなわち以下のような断片(この例自 身は特に意味はない)があらわれる.

putStrLn $ show $ lis $ rn $ map read $ words l

これは,「words l の結果のデータが map read に入り,その結果が rn に入 り,その結果が lis に入り,その結果が show に入り,その結果が putStrLn に入る.」というわけである. $ が一種のジョイントとみなせる.そこで, ここを通過するデータをチェックしたいとき用に .$. というオペレーターを 定義しよう.

infixr 0 .$.
(.$.) :: Show a => (a -> b) -> a -> b
f .$. x = trace (show x) f x

このようにしておくと,$ の代りに .$. を使った場所で通過するデータを見 ることができる.(もちろん通過するデータの型はShowクラスのインスタンス である必要がある.)

putStrLn $ show $ lis .$. rn $ map read $ words l

のように書くと lis に入るデータを見ることができるというわけである.

ちょっと高階

Haskellプログラミングになれてくると,処理の連結には関数適用オペレーター ($) ではなく関数合成オペレーター (.) になることが普通になる.

getLine >>= putStrLn . show . lis . rn . map read . words

などという断片が多用されるにちがいない.このとき (.) もジョイントのよ うなものだ.そこで (.) を通過するデータを見るためのオペレーター (…) を定義しよう.

infixr 9 ...
(...) :: Show b => (b -> c) -> (a -> b) -> (a -> c)
f ... g = (f .$.) . g 

これで,

getLine >>= putStrLn . show . lis ... rn . map read . words

と書くと rn の結果が lis の入るところでそのデータを見ることができると いうわけである.


Last modified : 2007/07/04 10:53:31 JST