liveBook · Manning

WC

As explained in Functional Programming in Scala, Second Edition

WC is an algebraic data type representing a partial word-count result with complete-word counts and unfinished words at its boundaries.

WC is an algebraic data type for a partial word-count result. A Stub holds characters when no complete word is known. A Part holds a left unfinished word, a count of definitely complete words, and a right unfinished word. The boundary strings remain uncounted because adjoining input may extend them into words. section 10.4

enum WC:
  case Stub(chars: String)
  case Part(lStub: String, words: Int, rStub: String)

The two cases distinguish a segment containing only an unresolved run of characters from one that has complete words between unresolved boundary runs. section 10.4

Partial results preserve uncertainty

Scanning "lorem ipsum do" yields Part("lorem", 1, "do"): only "ipsum" is certainly complete. Scanning "lor sit amet, " yields Part("lor", 2, ""). Keeping the boundary stubs makes independently scanned substrings safe to combine later. section 10.4

WC becomes useful when word counting is split into pieces. Its monoid combines adjacent partial results while preserving character order. Two stubs concatenate into a stub. A stub adjoining a part extends that part’s matching boundary. Two parts retain the outer boundaries, add their known counts, and add one more word exactly when the touching inner stubs are nonempty. section 10.9

The identity must be Stub(""). Using Part("", 0, "") instead breaks the identity law: combining it with Stub("a") changes the representation to Part("a", 0, ""), even though no input information changed. Generated WC values can check associativity and identity automatically. section 10.9

Counting a complete string

Map each non-whitespace character to a one-character Stub and each whitespace character to Part("", 0, ""). Fold the character sequence with wcMonoid, then count each nonempty remaining boundary stub as one word. This permits recursive splitting and recombination without losing words that cross a split. section 10.9 section 10.4

The character-to-WC mapping preserves the relevant combination structure: mapping adjacent input pieces and combining their WC values agrees with combining the input first and then mapping. This is the monoid-homomorphism property, which can be checked alongside the monoid laws. section 10.4

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Works through WC cases, all combination rules, identity-law failure, generated-law testing, and a character-folding implementation.
Examples
Uses "lorem ipsum do", "lor sit amet, ", character mapping, generated WC values, and a word-count function.
What it assumes
Uses algebraic data types, pattern matching, monoids, and folding while explaining WC’s boundary-state representation concretely.
What you can do after
Build it from scratch as a lawful WC monoid and apply it through foldMapV to count words.
How it connects
Connects WC to monoids, monoid laws, monoid homomorphisms, foldMapV, and parallel parsing.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.