{-# LANGUAGE DeriveGeneric #-}
module Control.Restartable.Checkpoint(restartable, Ending(..)) where
import Data.Aeson ( decodeFileStrict, encodeFile )
import GHC.Generics(Generic)
import System.Posix.Process(executeFile)
import System.Environment(getArgs, getProgName)
import System.IO.Error ( catchIOError )
import Control.Restartable.Initial
restore :: Initial a => FilePath -> IO a
restore filepath = do
result <- decodeFileStrict filepath `catchIOError` (\_ -> return $ Just initial)
case result of
Nothing -> error "Cannot load initial value!"
Just x -> return x
data Ending = Quit
| Restart
| Continue
deriving (Eq, Ord, Show, Generic)
restartExecutable :: IO ()
restartExecutable = do
args <- getArgs
exeName <- getProgName
executeFile exeName True args Nothing
restartable :: Initial a
=> FilePath
-> (a -> IO (a, Ending))
-> IO ()
restartable savefile app = do
initialState <- restore savefile
go initialState
where
go initialState = do
(finalState, ending) <- app initialState
encodeFile savefile finalState
case ending of
Restart -> restartExecutable
Continue -> go finalState
Quit -> return ()