[Haskell-cafe] simple word processor

Olaf Klinke olf at aatal-apotheke.de
Wed Oct 27 19:09:34 UTC 2021


> I am new to haskell and I need to create a simple word processor. It needs
> to read text from the cmd and implement functions that would edit functions
> found in the text so some other text.All functions in the text are odered.
> Each function i.e section,table,figures and ref must be located and
> numbered independently based on the order of occurence. Since tables and
> figures are within the sections function(just like a book), when a new
> section is encountered you will reset the value of tables and figures. So i
> did a loop where the tables and figures are inside the section loop when
> searching for the functions. The functions all start with this '' character
> (escape character) and must be replaced with text using this method:
> \Section{title}{id}: -> "Section n: title". Where n is the section number.
> \table{title}{id} : -> "Table n.m : title". Where n is the number of the
> last section encountered and m is the table number. And so on.

Let me try to break your problem into sub-problems. 
1. You have text where some patterns have meaning to your particular
application (e.g. "\Section{title}{id}").
2. When knowing this structure, you want to transform it from front to
back while updating some counters. 
3. Once that transformation is done, you want to write the structure
back into a plain text. 

How to approach: 

1. is addressed with parsers. There are plenty to choose from, e.g.
parsec, attoparsec, megaparsec to name just tree applicative-style
libraries. A parser looks for patterns in plain text and transforms it
into a more stuctured type. The structured type may be somethig like 
data Block a = SomeText Text
   | Section Text a
   | Table   Text s
   | etc.
The parsing function will have a type similar to
Text -> Either ParseError [Block ()]
where () stands for a numbering that is not yet known. 

2. May be modeled as a stateful traversal.
First define a state with all the counters, say
data Counters = Counters {
  theSection :: Int,
  theTable :: Int}
Next define a traversal function
Block () -> State Counters (Block Text)
where the unknown numbering () is replaced with the appropriate Text-
representation of theSection or (theSection,theTable) etc. 
Finally, traverse your parsed list of Blocks with this traversal.

3. essentially requires a Show instance for your (Block Text) type
together with concatenation. 

Steps 1-3 will be combined like follows. 

fmap ((=<<) show . flip evalState start . traverse number) . parse 
where
   parser :: Text -> Either ParseError [Block ()]
   start  :: Counters
   number :: Block () -> State Counters (Block Text)

"traversal" -> hoogle for Data.Traversable
"stateful" -> hoogle for Control.Monad.State


Olaf



More information about the Haskell-Cafe mailing list