@@ -1,44 +1,41 @@
1−module WordCount (foldWith, foldCountElements, printSelecttedOutput, WCOutputs(..)) where
1+module WordCount (foldWith, foldCountElements, printSelecttedOutput) where
3import Streamly.Data.Fold (Fold)
3import Streamly.Data.Fold (Fold)
5import qualified Streamly.Data.Stream as Stream
4import qualified Streamly.Data.Stream as Stream
6−import Data.Word (Word8)
7import qualified Streamly.Data.Fold as Fold
5import qualified Streamly.Data.Fold as Fold
8import qualified Streamly.FileSystem.File as File
6import qualified Streamly.FileSystem.File as File
9import Data.Function ((&))
7import Data.Function ((&))
9+import qualified Streamly.Unicode.Stream as Stream
11−foldWith :: Fold IO Word8 a -> String -> IO a
11+isSpace :: Char -> Bool
12−foldWith f file =
12+isSpace c = uc == 0x20 || uc - 0x9 <= 4
13− File.read file
13+ where uc = fromIntegral (ord c) :: Word
16data WCOutputs =
15data WCOutputs =
17 WCOutputs {
16 WCOutputs {
18− bytesCount :: !Int
17+ charCount :: !Int
19− , charCount :: !Int
18+ , wordsCount :: !Int
20 , lineCount :: !Int
19 , lineCount :: !Int
20+ , isSpaceChar :: !Bool
22 deriving (Show)
22 deriving (Show)
24−instance Semigroup WCOutputs where
24+count :: WCOutputs -> Char -> WCOutputs
25− (WCOutputs a b c) <> (WCOutputs a' b' c') = WCOutputs (a + a') (b + b') (c + c')
25+count (WCOutputs charsAmount wordsAmount linesAmount wasSpace) char =
26−
26+ let newLinesAmount = if char == '\n' then linesAmount + 1 else linesAmount
27−instance Monoid WCOutputs where
27+ (newWordsAmount, isSpaceChar) = if isSpace char then (wordsAmount, True)
28− mempty = WCOutputs 0 0 0
28+ else (if wasSpace then wordsAmount + 1 else wordsAmount, False)
29+ in WCOutputs (charsAmount + 1) newWordsAmount newLinesAmount isSpaceChar
30−countElements :: Word8 -> WCOutputs
31+foldWith :: Fold IO Char a -> String -> IO a
31−countElements c =
32+foldWith f file =
32− WCOutputs {
33+ File.read file
33− bytesCount = 1
34+ & Stream.decodeUtf8
34− , charCount = if isContinuationByte then 0 else 1
35+ & Stream.fold f
35− , lineCount = if c == 10 then 1 else 0
36+
38− isContinuationByte = (c .&. 0xC0) == 0x80
40−foldCountElements :: Fold IO Word8 WCOutputs
37+foldCountElements :: Fold IO Char WCOutputs
41−foldCountElements = Fold.foldl' (\a b -> a <> countElements b) mempty
38+foldCountElements = Fold.foldl' count (WCOutputs 0 0 0 True)
43printSelecttedOutput :: WCOutputs -> String
40printSelecttedOutput :: WCOutputs -> String
44−printSelecttedOutput output = show (lineCount output) ++ " " ++ show (charCount output) ++ " " ++ show (bytesCount output)
41+printSelecttedOutput output = show (lineCount output) ++ " " ++ show (wordsCount output) ++ " " ++ show (charCount output)