
Patrick LeBoutillier
Amy,
Here's a small suggestion:
If the start and loop functions always returns Nothing, I think it may be cleaner to simply make them return ().
Thank you Patrick, that make the interface easier for the user to understand. The "loop" function does return something when it is called recursively, but the outer call never returns anything, so my first try was to have two separate functions. ----- code snippet ----- loop :: (a -> IO a) -> (a -> IO ()) -> a -> IO () loop work finalise d = loop' work finalise d >> return () loop' :: (a -> IO a) -> (a -> IO ()) -> a -> IO (Maybe a) loop' work finalise d = do timeToStop <- readMVar termReceived if timeToStop then finalise d >> return Nothing else work d >>= loop' work finalise ----- end of code snippet ----- But then I thought that looked more complicated, so I went with this. (CountingExample.hs is unchanged.) ----- Daemon.hs ----- module Daemon where import System.Exit import System.IO.Unsafe import System.Posix.Signals import Control.Concurrent termReceived = unsafePerformIO (newMVar False) handleTERM :: IO () handleTERM = swapMVar termReceived True >> return () loop :: (a -> IO a) -> (a -> IO ()) -> a -> IO (Maybe a) loop work finalise d = do timeToStop <- readMVar termReceived if timeToStop then finalise d >> return Nothing else work d >>= loop work finalise start -- | This function will be invoked when the daemon starts. :: IO a -- | This function will be invoked in the main loop. -> (a -> IO a) -- | This function will be invoked when the daemon shuts down. -> (a -> IO ()) -- | Returns nothing. -> IO () start initialise work finalise = installHandler sigTERM (Catch handleTERM) Nothing >> initialise >>= loop work finalise >> return ()