wc そのに

id:ha-tan:20061112:1163293651のコードはやっぱりちょっとあんまりだと思うので、リファクタリングしようと思います。とりあえず行数、単語数、バイト数を数える部分を1パスにしてみます。インターフェースが前のと違うけど、まぁいいか。

module Main (main) where

import Data.Char (isSpace)
import System.IO (stdin, hSetBinaryMode)

getBinaryContents :: IO String
getBinaryContents = do
  hSetBinaryMode stdin True
  getContents

wc :: String -> (Int, Int, Int)
wc = wc' (0, 0, 0) False
  where
    wc' (l, w, b) sp []
      | sp        = (l, w,     b)
      | otherwise = (l, w + 1, b)
    wc' (l, w, b) sp (x : xs)
      | x == '\n'       = wc' (l + 1, w, b + 1) True  xs
      | sp && isSpace x = wc' (l,     w, b + 1) True  xs
      | isSpace x       = wc' (l, w + 1, b + 1) True  xs
      | otherwise       = wc' (l,     w, b + 1) False xs

main :: IO ()
main = print . wc =<< getBinaryContents

(追記) あれ、これだと簡単にスタックオーバーフローしちゃうな。うーむ。どうしたらいいんだろう。

$ ls -l c:/usr/cygwin/bin/cygcrypto-0.9.7.dll
-rwxr-x---+ 1 s-tanaka Users 1134891 Jun  2 01:00 c:/usr/cygwin/bin/cygcrypto-0.9.7.dll
$ ./wc < c:/usr/cygwin/bin/cygcrypto-0.9.7.dll
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize' to increase it.