{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE RecordWildCards #-}
module Advent.Cache (
cacheing
, SaverLoader(..)
, noCache
) where
import Control.DeepSeq
import Control.Exception
import Control.Monad
import Control.Monad.IO.Class
import Data.Text (Text)
import System.Directory
import System.FilePath
import System.IO.Error
import qualified Data.Text.IO as T
data SaverLoader a =
SL { _slSave :: a -> Maybe Text
, _slLoad :: Text -> Maybe a
}
noCache :: SaverLoader a
noCache = SL (const Nothing) (const Nothing)
cacheing
:: MonadIO m
=> FilePath
-> SaverLoader a
-> m a
-> m a
cacheing fp SL{..} act = do
old <- liftIO $ do
createDirectoryIfMissing True (takeDirectory fp)
(_slLoad =<<) <$> readFileMaybe fp
case old of
Nothing -> do
r <- act
liftIO . mapM_ (T.writeFile fp) $ _slSave r
pure r
Just o -> pure o
readFileMaybe :: FilePath -> IO (Maybe Text)
readFileMaybe =
(traverse (evaluate . force) . either (const Nothing) Just =<<)
. tryJust (guard . isDoesNotExistError)
. T.readFile