module ALife.Creatur.Counter
(
Counter(..),
PersistentCounter,
mkPersistentCounter
) where
import ALife.Creatur.Clock (Clock, currentTime, incTime)
import Control.Monad (unless)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.State (StateT, get, gets, modify, put)
import System.Directory (doesFileExist)
class Counter c where
current ∷ StateT c IO Int
increment ∷ StateT c IO ()
data PersistentCounter = PersistentCounter {
initialised ∷ Bool,
time ∷ Int,
filename ∷ FilePath
} deriving Show
mkPersistentCounter ∷ FilePath → PersistentCounter
mkPersistentCounter = PersistentCounter False (1)
instance Counter PersistentCounter where
current = do
initIfNeeded
gets time
increment = do
t ← current
let t' = t + 1
f ← gets filename
modify (\c → c { time=t' })
liftIO $ writeFile f $ show t'
initIfNeeded ∷ StateT PersistentCounter IO ()
initIfNeeded = do
isInitialised ← gets initialised
unless isInitialised $ do
counter ← get
counter' ← liftIO $ initialise counter
put counter'
initialise ∷ PersistentCounter → IO PersistentCounter
initialise counter = do
let f = filename counter
fExists ← doesFileExist f
if fExists
then do
s ← readFile f
return $ counter { initialised=True, time=read s }
else return $ counter { initialised=True, time=0 }
instance Clock PersistentCounter where
currentTime = current
incTime = increment