Skip to content

Instantly share code, notes, and snippets.

@beala
Created May 29, 2015 16:52
Show Gist options
  • Save beala/465b34be4701a8144883 to your computer and use it in GitHub Desktop.
Save beala/465b34be4701a8144883 to your computer and use it in GitHub Desktop.
Free Timer monad with multiple interpreters
{-# LANGUAGE DeriveFunctor #-}
import Control.Concurrent.Timer
import Control.Concurrent.Suspend.Lifted
import Control.Monad.Free
import GHC.Int (Int64)
import Control.Monad.Writer.Lazy
-- Timer type to be lifted into Free.
data TimerM r = TimerM Int64 (IO ()) r deriving (Functor)
-- Constructor for a Timer action.
timer :: Int64 -> IO () -> Free TimerM ()
timer d a = liftF $ TimerM d a ()
-- Interpreter for running the timers.
eval :: TimerM a -> IO a
eval (TimerM d a r) = do
oneShotTimer a (sDelay d)
return r
-- Interpreter for recording actions.
evalTest :: TimerM a -> Writer [String] a
evalTest (TimerM d a r) = do
tell ["Timer set for " ++ (show d) ++ " seconds.\n"]
return r
-- > execWriter $ foldFree evalTest $ do
-- timer 1 (putStrLn "hi")
-- timer 2 (putStrLn "mmk")
--
-- ["Timer set for 1 seconds.\n","Timer set for 2 seconds.\n"]
-- > foldFree eval $ do
-- timer 1 (putStrLn "hi")
-- timer 2 (putStrLn "mmk")
--
-- hi (one second later)
-- mmk (two seconds later)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment