Online Book Reader

Home Category

Beautiful Code [274]

By Root 5175 0
bricks that can be glued together—using do {…}, retry, and orElse—to make bigger STM actions. However, as soon as you wrap a block in atomically, making it an IO type, it can no longer be combined atomically with other actions. There is a good reason for that: a value of IO type can perform arbitrary, irrevocable input/output (such as launchMissiles).

It is therefore good library design to export STM actions (rather than IO actions) whenever possible, because they are composable; their type advertises that they have no irrevocable effects. The library client can readily get from STM to IO (using atomically), but not vice versa.

Sometimes, however, it is essential to use an IO action. Look at operateGate. The two calls to atomically cannot be combined into one, because the first has an externally visible side effect (opening the gate), while the second blocks until all the elves have woken up and gone through it. So, operateGate must have an IO type.

24.3.3. The Main Program

We will first implement the outer structure of the program, although we have not yet implemented Santa himself. Here it is:

main = do { elf_group <- newGroup 3

; sequence_ [ elf elf_group n | n <- [1..10] ]

; rein_group <- newGroup 9

; sequence_ [ reindeer rein_group n | n <- [1..9] ]

; forever (santa elf_group rein_group) }

The first line creates a Group for the elves with capacity 3. The second line is more mysterious: it uses a so-called list comprehension to create a list of IO actions and calls sequence_ to execute them in sequence. The list comprehension [e|x<-xs] is read, "the list of all e where x is drawn from the list xs." So, the argument to sequence_ is the list:

[elf elf_group 1, elf elf_group 2, ..., elf elf_group 10]

Each of these calls yields an IO action that spawns an elf thread. The function sequence_ takes a list of IO actions and returns an action that, when performed, runs each of the actions in the list in order:[]

[] The type [IO a] means "a list of values of type IO a." You may also wonder about the underscore in the name sequence_: it's because there is a related function sequence, whose type is [IO a] -> IO [a], that gathers the results of the argument actions into a list. Both sequence and sequence_ are defined in the Prelude library, which is imported by default.

sequence_ :: [IO a] -> IO ( )

An elf is built from elf1, but with two differences. First, we want the elf to loop indefinitely, and second, we want it to run in a separate thread:

elf :: Group -> Int -> IO ThreadId

elf gp id = forkIO (forever (do { elf1 gp id; randomDelay }))

The forkIO part spawns its argument as a separate Haskell thread (see the earlier section "Side Effects and Input/Output in Haskell"). In turn, forkIO's argument is a call to forever, which runs its argument repeatedly (compare to the definition of nTimes in "Side Effects and Input/Output in Haskell"):

forever :: IO () -> IO ( )

-- Repeatedly perform the action

forever act = do { act; forever act }

Finally, the expression (elf1 gp id) is an IO action, and we want to repeat that action indefinitely, followed each time by a random delay:

randomDelay :: IO ( )

-- Delay for a random time between 1 and 1,000,000 microseconds

randomDelay = do { waitTime <- getStdRandom (randomR (1, 1000000))

; threadDelay waitTime }

The rest of the main program should be self-explanatory. We make 9 reindeer in the same way that we made 10 elves, except that we call reindeer instead of elf:

reindeer :: Group -> Int -> IO ThreadId

reindeer gp id = forkIO (forever (do { reindeer1 gp id; randomDelay }))

The code for main finishes by reusing forever to run santa repeatedly. All that remains is to implement Santa himself.

24.3.4. Implementing Santa

Santa is the most interesting participant of this little drama because he makes choices. He must wait until there is either a group of reindeer waiting or a group of elves. Once he has made his choice of which group to attend to, he must take them through their task. Here is his code:

santa

Return Main Page Previous Page Next Page

®Online Book Reader