Enumerating Haiku
rule
starters
7.3

Enumerating Haiku

Programs written in the haiku-enum language define an enumeration of Haiku use the same concrete syntax as for Scribble (described in @ Syntax), except starting in normal racket mode instead of starting in text mode.
The haiku generated by a program in haiku-enum follow the rules and the vocabulary specified in the program. Rules are defined in two parts: a use of starters that indicates how the haiku begin and then a series of uses of rule that determine how the haiku continue (and end).
The vocabulary is specified at the end of the file, using the parts of speech introduced by the rules.

For example, consider this simple program in haiku-enum that has a set of rules that generate some especially boring Haiku:
  #lang haiku-enum
   
  (starters
   (adjective noun))
   
  (rule noun ->
        verb)
   
  (rule verb ->
        #:comma adjective)
   
  (rule adjective ->
        noun)
   
  @adjective[1]{black fierce gray plump wet}
  @adjective[2]{achy agile dormant mangy sober wrinkled}
  @noun[1]{ant owl stag wasp}
  @noun[2]{duckling panda songbird swordfish}
  @verb[1]{aches barks claws climbs roves snarls weeps}
  @verb[2]{awaits beckons gallops gambols slobbers}
   

The starters part of the program declares that the Haiku must all begin with an adjective and then transition to the noun state (multiple possible starting parts of speech are allowed; just parenthesize each possibility).
The rules describe the valid states. When in the noun state, the language will generate a noun and then transition to the verb state, as declared just below the starters section in the first rule. Similarly, a verb must be followed by a comma and then an adjective, and the cycle continues.
After all of the rules, the vocabulary is declared. Each vocabulary declaration consists of the number of syllables, followed by words that are in that category of the part of speech and have that many syllables. Use one declaration for each different number of syllables that words in the part of speech may have.

This file then provides:
  • random-haiku: a function that accepts no arguments and returns a random haiku (as a string),

  • how-many-haiku:, a natural number that indicates how many different haiku this program generates,

  • nth-haiku: a function that accepts a natural number less than how-many-haiku and returns the corresponding haiku, and

  • enum/e: a one-way enumeration of the same haiku that nth-haiku returns

  • structured-haiku/e: a two-way enumeration that maps the naturals to an sexpression representing the choices made to construct a particular haiku

Examples:
> (display (nth-haiku 0))

fierce wasp snarls, fierce wasp

snarls, fierce wasp snarls, fierce wasp snarls,

fierce wasp snarls, fierce wasp

> (display (nth-haiku (- how-many-haiku 1)))

achy panda aches,

achy panda slobbers, wet

panda slobbers, wet

> (display (nth-haiku (quotient (- how-many-haiku 1) 2)))

plump panda barks, gray

stag climbs, wet stag claws, black wasp

weeps, plump stag roves, plump

The library also contains the file "haiku.rkt", a more elaborate example that contains haiku such as these:
> (display (nth-haiku 145095608713658901635917363016718021515))

drab geese smear, Bela

blares, cool plain hag grunts, shy hawks

drink, great green pines rage

> (display (nth-haiku 5842574289046493184639147839447824095))

drab palms weep, lush broad

hog bolts, moths hobble, spear freezes,

chaste pain blazes, alert

The "haiku.rkt" program is a reimplementation of the program that generates random haiku from http://www.everypoet.com/haiku/.

syntax

(rule haiku-state-id word-class-id -> next-state ...)

(rule haiku-state-id -> next-state ...)
 
next-state = maybe-lastness maybe-comma haiku-state-id
     
maybe-lastness = 
  | #:only-last
  | #:not-last
     
maybe-comma = 
  | #:comma
Defines a state for haiku named haiku-state-id that, when entered, generates a word from word-class-id and then transitions to one of the states listed in next-state. If word-class-id does not appear, then haiku-state-id is taken as both the name of the state and the name of the class of words to generate.

If #:only-last appears, then this state is entered only when it would be the last word in the haiku. If #:not-last appears, then this state is entered only when it would not be the last word in the haiku.

If #:comma appears, then a comma is generated in the haiku before continuing into the next state.

In addition to defining a new rule, a use of rule defines word-class-id (if the first case is used) or haiku-state-id (if the second case is used). It is defined to accept a natural number and a sequence of strings that are assumed to be words that all have the given number of syllables. The name can be used multiple times with different numbers of syllables.

For example, the rule

(rule adjective -> noun)

generates a rule that transitions from the adjective state to the noun state and admits the possibility of defining adjectives by using adjective, e.g.,
(adjective 1 "tall" "fast")
(adjective 2 "three-point" "driven")
(adjective 3 "athletic")
Use underscores in the word if it should be rendered with a space but count as a single item in a haiku (i.e., it should either appear entirely or not at all), e.g.:

(noun 4 "Michael_Jordan")

which appears as "Michael Jordan" but never "Michael" or "Jordan" on their own.

syntax

(starters (word-class-id haiku-state-id) ...)

Starts a haiku.

Each clause indicates one way that a haiku can start, namely by generating a word from word-class-id and then moving into the state haiku-state-id.