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