module Data.IORef.RunOnce (runOnce) where import Control.Monad.IO.Class import Data.IORef runOnce :: MonadIO m => m a -> m (m a) runOnce f = do ref <- liftIO $ newIORef Nothing return $ do mval <- liftIO $ readIORef ref case mval of Just val -> return val Nothing -> do val <- f liftIO $ writeIORef ref (Just val) return val