{-# LANGUAGE RecursiveDo #-}
module Reactive.Banana.Prim.Cached (
Cached, runCached, cache, fromPure, don'tCache,
liftCached1, liftCached2,
) where
import Control.Monad
import Control.Monad.Fix
import Control.Monad.IO.Class
import Data.IORef
import System.IO.Unsafe (unsafePerformIO)
data Cached m a = Cached (m a)
runCached :: Cached m a -> m a
runCached (Cached x) = x
{-# NOINLINE cache #-}
cache :: (MonadFix m, MonadIO m) => m a -> Cached m a
cache m = unsafePerformIO $ do
key <- liftIO $ newIORef Nothing
return $ Cached $ do
ma <- liftIO $ readIORef key
case ma of
Just a -> return a
Nothing -> mdo
liftIO $
writeIORef key (Just a)
a <- m
return a
fromPure :: Monad m => a -> Cached m a
fromPure = Cached . return
don'tCache :: Monad m => m a -> Cached m a
don'tCache = Cached
liftCached1 :: (MonadFix m, MonadIO m) =>
(a -> m b) -> Cached m a -> Cached m b
liftCached1 f ca = cache $ do
a <- runCached ca
f a
liftCached2 :: (MonadFix m, MonadIO m) =>
(a -> b -> m c) -> Cached m a -> Cached m b -> Cached m c
liftCached2 f ca cb = cache $ do
a <- runCached ca
b <- runCached cb
f a b