Ieratee IO example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
module Main where

import Data.Enumerator as E
import qualified Data.Enumerator.Binary as EB
import qualified Data.Enumerator.Text as ET
import qualified Data.Enumerator.List as EL
import qualified Data.ByteString as B
import Data.Ord
import qualified Data.Text as T
import qualified Data.List as L
import System.IO (stdin)

-- a simple function to find the longest run of equal elements in a list
-- *Main> consecList "dddddkkkksllllllllllddddddddddkkkkkkkkkkkkkkk"
-- (15,'k')

pairWith f g a = (f a, g a)
consecList [] = (0,undefined)
consecList xs = (L.maximumBy (comparing fst)) . (L.map (pairWith L.length L.head)) . L.group $ xs

-- the same idea, but for characters in a file using Iteratee IO.

maximumByIteratee :: Monad m => (a -> a -> Ordering) -> a -> Iteratee a m a
maximumByIteratee mx least = EL.fold f least
    where
      f acc a = case mx acc a of GT -> acc
                                 _ -> a

groupByEnumeratee :: Monad m => (a -> a -> Bool) -> Enumeratee a [a] m b
groupByEnumeratee predicate = E.sequence $ 
                              do
                                maybeNxt <- EL.head
                                case maybeNxt of
                                     Nothing -> return []
                                     Just nxt -> do xs <- EL.takeWhile (predicate nxt) 
                                                    return $ nxt : xs

mainEnumerator = ET.enumHandle stdin $$                              -- read text from stdin
                 (
                  EL.concatMap T.unpack                              -- convert a stream of texts to a stream of chars (1 to M)
                  =$ groupByEnumeratee (==)                          -- group same characters (M to 1)
                  =$ EL.map (pairWith L.length L.head)               -- count the characters
                  =$ maximumByIteratee (comparing fst) (0,undefined) -- output the greatest
                 ) 

main =
    do
      result@(howMany, which) <- run_ mainEnumerator
      if howMany == 0 
      then print "Empty file." 
      else print result