Minimal Haskell Unit Testing Framework
Replace explicit recursion with library combinators. Unduplicate and inline as much as possible.

testImpl :: Int -&gt; (Bool, String) -&gt; String 
testImpl i (cond, msg) = unwords $
  [ if cond then "ok" else "not ok"
  , show i
  ] ++ case msg of [] -&gt; []; m -&gt; ["-", m]

tests :: [(Bool, String)] -&gt; IO ()
tests xs = do
  putStrLn $ unlines $ zipWith testImpl [1..] xs
  putStrLn $ "1.." ++ show (length xs)
  if all fst xs then exitSuccess else exitFailure