git.iko.soy/Fraudik/haskell-web-wc
on main help sign in
Implement words counting
commita7b796a9e91d4e6e5afd3c09591b4a1c59788285 authorBlinov Ilya <ulkhan.2014@mail.ru> dateTue 25 Mar 2025, 19:58 (2 years ago) parentca5d7eb
2 files changed+27−28
README.md+3−1 src/WordCount.hs+24−27
README.md+3−1
@@ -9,8 +9,10 @@
99## Состояние проекта
1010
1111[x] Первая версия, Proof of Concept. Просто работа с MultipartForm запросами, реализация wc из домашнего задания, тестирование через отправку этого README.
12−[x] Подготовлен тестовый файл: sample.txt в 1,12 ГБ. Статистики для него: 25018508 1209339403 1209339403
12+[x] Подготовлен тестовый файл: sample.txt в 1,12 ГБ. Статистики первого wc для него: 25018508 194885810 1209339403 (строки, слова, символы)
13+[x] Реализован подсчет слов, проверена корректность
1314
1415## Анализ производительности
1516
16171. Proof of Concept: Elapsed (wall clock) time (h:mm:ss or m:ss): 0:27.25, Maximum resident set size (kbytes): 1816
18+2. Подсчет слов: Elapsed (wall clock) time (h:mm:ss or m:ss): 0:39.20, Maximum resident set size (kbytes): 1816
src/WordCount.hs+24−27
@@ -1,44 +1,41 @@
1−module WordCount (foldWith, foldCountElements, printSelecttedOutput, WCOutputs(..)) where
1+module WordCount (foldWith, foldCountElements, printSelecttedOutput) where
22
33import Streamly.Data.Fold (Fold)
4−import Data.Bits
54import qualified Streamly.Data.Stream as Stream
6−import Data.Word (Word8)
75import qualified Streamly.Data.Fold as Fold
86import qualified Streamly.FileSystem.File as File
97import Data.Function ((&))
8+import Data.Char (ord)
9+import qualified Streamly.Unicode.Stream as Stream
1010
11−foldWith :: Fold IO Word8 a -> String -> IO a
12−foldWith f file =
13− File.read file
14− & Stream.fold f
11+isSpace :: Char -> Bool
12+isSpace c = uc == 0x20 || uc - 0x9 <= 4
13+ where uc = fromIntegral (ord c) :: Word
1514
1615data WCOutputs =
1716 WCOutputs {
18− bytesCount :: !Int
19− , charCount :: !Int
17+ charCount :: !Int
18+ , wordsCount :: !Int
2019 , lineCount :: !Int
20+ , isSpaceChar :: !Bool
2121 }
2222 deriving (Show)
2323
24−instance Semigroup WCOutputs where
25− (WCOutputs a b c) <> (WCOutputs a' b' c') = WCOutputs (a + a') (b + b') (c + c')
26−
27−instance Monoid WCOutputs where
28− mempty = WCOutputs 0 0 0
24+count :: WCOutputs -> Char -> WCOutputs
25+count (WCOutputs charsAmount wordsAmount linesAmount wasSpace) char =
26+ let newLinesAmount = if char == '\n' then linesAmount + 1 else linesAmount
27+ (newWordsAmount, isSpaceChar) = if isSpace char then (wordsAmount, True)
28+ else (if wasSpace then wordsAmount + 1 else wordsAmount, False)
29+ in WCOutputs (charsAmount + 1) newWordsAmount newLinesAmount isSpaceChar
2930
30−countElements :: Word8 -> WCOutputs
31−countElements c =
32− WCOutputs {
33− bytesCount = 1
34− , charCount = if isContinuationByte then 0 else 1
35− , lineCount = if c == 10 then 1 else 0
36− }
37− where
38− isContinuationByte = (c .&. 0xC0) == 0x80
39−
40−foldCountElements :: Fold IO Word8 WCOutputs
41−foldCountElements = Fold.foldl' (\a b -> a <> countElements b) mempty
31+foldWith :: Fold IO Char a -> String -> IO a
32+foldWith f file =
33+ File.read file
34+ & Stream.decodeUtf8
35+ & Stream.fold f
36+
37+foldCountElements :: Fold IO Char WCOutputs
38+foldCountElements = Fold.foldl' count (WCOutputs 0 0 0 True)
4239
4340printSelecttedOutput :: 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)