[Haskell-cafe] Software Tools in Haskell

Benja Fallenstein benja.fallenstein at gmail.com
Fri Dec 14 22:39:09 EST 2007

On Dec 14, 2007 9:29 AM, Henning Thielemann
<lemming at henning-thielemann.de> wrote:
> I remember there was a discussion about how to implement full 'wc' in an
> elegant but maximally lazy form, that is counting bytes, words and lines
> in one go. Did someone have a nice idea of how to compose the three
> counters from implementations of each counter? I'm afraid one cannot
> simply use the "split and count fragments" trick then.

Could you turn the folds into scans and use zip3 and last? I.e.,
something like this:

data Triple a b c = Triple !a !b !c deriving Show

countChars :: String -> [Int]
countChars = scanl (\n _ -> n+1) 0

countChar :: Char -> String -> [Int]
countChar c = scanl (\n c' -> if c == c' then n+1 else n) 0

countLines = countChar '\n'
countWords = countChar ' '

last' [x] = x
last' (x:xs) = x `seq` last' xs

zip3' (x:xs) (y:ys) (z:zs) = Triple x y z : zip3' xs ys zs
zip3' _ _ _ = []

wc :: String -> Triple Int Int Int
wc xs = last' $ zip3' (countChars xs) (countWords xs) (countLines xs)

main = print . wc =<< getContents

(or use Data.Strict.Tuple -- but that only has pairs and no zip...)

- Benja

More information about the Haskell-Cafe mailing list