Santa
From HaskellWiki
ChrisKuklewicz 14:05, 25 June 2007 (UTC) In response to the link to an Erlang comparision at the wiki page Talk:SantaClausProblem , I am posting this roughly 34 lines of code adaptation of the Erlang message passing soultion:
-- by Chris Kuklewicz, looking at http://www.cs.otago.ac.nz/staffpriv/ok/santa/index.htm
-- This makes extensive use of sending partly or fully curried
-- commands through Chan and TChan. Reindeer priority is implemented
-- using 'orElse'. I did away with the extra secretary threads, since they
-- were not needed. I used (replicateM count (readTChan chan))) instead.
-- Santa should really use a Control.Concurrent.QSemN
module Santa(main) where
import Control.Monad(replicateM,replicateM_)
import Control.Concurrent(newChan,readChan,writeChan,threadDelay,forkIO)
import Control.Concurrent.STM(newTChanIO,readTChan,writeTChan,orElse,atomically)
import System.Random(randomRIO)
data Species a = Reindeer [a] | Elves [a]
forever x = x >> forever x
santa getNext self = forever (getNext >>= handle) where
handle (Reindeer group) = do putStr "Ho, ho, ho! Let's deliver toys!\n"
act group
handle (Elves group) = do putStr "Ho, ho, ho! Let's meet in the study!\n"
act group
act group = do sequence_ [tellMember (writeChan self ()) | tellMember <- group]
replicateM_ (length group) (readChan self)
worker tellSecretary msg self = forever $ do
threadDelay =<< randomRIO (0,1000*1000) -- 0 to 1 second
tellSecretary (writeChan self)
tellGateKeeperIamDone <- readChan self
putStr msg
tellGateKeeperIamDone
spawnWorker tellSecretary before i after =
forkIO (newChan >>= worker tellSecretary (before ++ show i ++ after))
secretary count species = do
chan <- newTChanIO
return (writeTChan chan,fmap species (replicateM count (readTChan chan)))
main = do
(toRobin,fromRobin) <- secretary 9 Reindeer
(toEdna,fromEdna) <- secretary 3 Elves
sequence [ spawnWorker (atomically . toRobin) "Reindeer " i " delivering toys.\n"
| i <- [1..9] ]
sequence [ spawnWorker (atomically . toEdna) "Elf " i " meeting in the study.\n"
| i <- [1..10] ]
newChan >>= santa (atomically (fromRobin `orElse` fromEdna)) -- main thread is santa's