Haskellでもデバッグプリントしたい + Sコンビネータの練習

いきなりですが、やっぱりHaskellでもデバッグプリントしたいですよね。調べた結果、Debug.Traceにある関数traceを使えばできることがわかりました。おお、副作用が… 実装はきっと暗黒面なんだろうな(キレイな身体じゃ生きられない、みたいな)。
そのまま使ってもいいんですが、せっかくなんでRubyっぽく関数pを定義してみました。
ファイル: a.hs

module Main (main) where

import Debug.Trace (trace)

p :: (Show a) => a -> a
p = p' ""

p' :: (Show a) => String -> a -> a
p' s a = trace (s ++ show a) a

inc :: Int -> Int
inc i = i + 1

main :: IO ()
main = print $ p $ inc 10

実行例:

$ runghc a.hs
11 ← デバッグプリントの出力。
11 ← printの出力。

ついでに。上のプログラムでは関数p'のとこで変数aを2回参照しています。Sコンビネータを使ったら簡単になるかなと思ってちょっと試してみました。以下、Sコンビネータに至るまでの手順です。

p' :: (Show a) => String -> a -> a
-- p' s a = trace (s ++ show a) a                   -- (1)
-- p' s a = flip trace a (s ++ show a)              -- (2)
-- p' s a = (flip trace) a $ ((++) s . show) a      -- (3)
-- p' s a = starling (flip trace) ((++) s . show) a -- (4)
p' s = starling (flip trace) ((++) s . show)        -- (5)
  where
    starling :: (a -> b -> c) -> (a -> b) -> a -> c
    starling f g x = f x (g x)

(1)オリジナル。(2)traceの引数の順番を入れ換える。(3)flipの辺でカリー化を意識する。showの辺を関数合成にする。(4)Sコンビネータを適用する。(5)変数aは不要なので消す。
うーむ。やっぱ(1)のままでいいや。(5)は読めません。