EDITED 2015-11-29 : see bottom
I am trying to write an application with a do-last-action-again button. The team in question may request input, and my thought on how to do this was to simply restart the resulting monad with memoized IO.
There are many posts on SO with similar questions, but none of the solutions seem to work here.
I removed the memoIO code from this SO answer and changed the implementation to MonadIO .
-- Memoize an IO function memoIO :: MonadIO m => ma -> m (ma) memoIO action = do ref <- liftIO $ newMVar Nothing return $ do x <- maybe action return =<< liftIO (takeMVar ref) liftIO . putMVar ref $ Just x return x
I have a small review of my approach to the application, the only real difference is that my application has a large transformer stack instead of just working in IO :
-- Global variable to contain the action we want to repeat actionToRepeat :: IORef (IO String) actionToRepeat = unsafePerformIO . newIORef $ return "" -- Run an action and store it as the action to repeat repeatable :: IO String -> IO String repeatable action = do writeIORef actionToRepeat action action -- Run the last action stored by repeatable doRepeat :: IO String doRepeat = do x <- readIORef actionToRepeat x
The idea is that I can save the action with memoized IO to IORef (via repeatable ) when I record what was done last and then repeat it with doRepeat .
I am testing this through:
-- IO function to memoize getName :: IO String getName = do putStr "name> " getLine main :: IO () main = do repeatable $ do memoized <- memoIO getName name <- memoized putStr "hello " putStrLn name return name doRepeat return ()
with expected output:
name> isovector hello isovector hello isovector
but the actual conclusion is:
name> isovector hello isovector name> wasnt memoized hello wasnt memoized
I'm not quite sure what the problem is, or even how to debug it. A gun to my head, I would suggest that a lazy assessment bites me, but I canโt understand where.
Thanks in advance!
EDIT 2015-11-29 . My intended use case for this is to implement repeat the last change of the statement in the vim clone. Each action can perform an arbitrary number of arbitrary I / O calls, and I would like it to indicate which ones should be stored in memory (reading a file, maybe not. User request for input, yes).