-- To run this program: -- -- cabal run --flag fusion-plugin WordCount test-data.txt -- module WordCount (main, count, Counts(..), isSpace) where import Data.Char (ord) import Data.Function ((&)) import System.Environment (getArgs) import Streamly.FileSystem.Path (Path) import qualified Streamly.Data.Fold as Fold import qualified Streamly.Data.Stream as Stream import qualified Streamly.FileSystem.FileIO as File import qualified Streamly.FileSystem.Path as Path import qualified Streamly.Unicode.Stream as Stream ------------------------------------------------------------------------------- -- C compatible isSpace ------------------------------------------------------------------------------- {-# INLINE isSpace #-} isSpace :: Char -> Bool isSpace c = uc == 0x20 || uc - 0x9 <= 4 where uc = fromIntegral (ord c) :: Word ------------------------------------------------------------------------------- -- Counting ------------------------------------------------------------------------------- -- Counts lines words chars lastCharWasSpace data Counts = Counts !Int !Int !Int !Bool deriving Show {-# INLINE count #-} count :: Counts -> Char -> Counts count (Counts l w c wasSpace) ch = let l1 = if ch == '\n' then l + 1 else l (w1, wasSpace1) = if isSpace ch then (w, True) else (if wasSpace then w + 1 else w, False) in Counts l1 w1 (c + 1) wasSpace1 wc :: Path -> IO Counts wc file = File.read file -- Stream IO Word8 & Stream.decodeLatin1 -- Stream IO Char -- & Stream.decodeUtf8 -- Stream IO Char & Stream.fold (Fold.foldl' count (Counts 0 0 0 True)) -- IO Counts ------------------------------------------------------------------------------- -- Main ------------------------------------------------------------------------------- main :: IO () main = do name <- fmap head getArgs nameP <- Path.fromString name Counts l w c _ <- wc nameP putStrLn $ show l ++ " " ++ show w ++ " " ++ show c ++ " " ++ name