In a Haskell system I don't have much control over, I provide a syntactically pure function with the following signature:
doTheWork :: Int -> TheInput -> MyResult
doTheWork counter data = ...
This function does some work and returns its result. However the function is called again and again (until the system resource are used up) with incremented Ints to do more work on the same problem (the same TheInput data).
So to make use of the fact to be called again and again and not every time start again, I would need to store the intermediate MyResults. Of course, the "proper" semantically pure way would be that the system calls the function together with the old last results; i.e. the function signature would be something like doTheWork :: MyResult -> Int -> TheInput -> MyResult, but I have no control over the signature. The signature my function has to conform to is the shown at the beginning of the question! And I cannot move the function into the IO Monad of the program (because I don't have control over where the function is called).
So I was thinking to store the MyResults myself in memory via unsafePerformIO or similar. However I got stuck on the "safe to memory part". I can print the results out to stdout with something like
storeMyResults :: MyResults -> MyResults
storeMyResults data =
unsafePerformIO $ do
putStrLn show data)
return data
and then use storeMyResults data at the end of doTheWork when returning the results to write them out each time the function has computed new results.
But I have no idea how to write the MyResults value to memory and then read it out the next time I get called. I think I could write it to a file, but that's unnecessarily slow.
Is there a way to store a value in a memory location?
The typical way to do this is to
unsafePerformIOyourself a top-levelIORef.IORefs normally provide "mutable memory location" functionality withinIO, but you can also break one out ofIO.At this point, you have a mutable, program-global variable, like you would in C.
Proceed to wire this into
doTheWork. Note to take care to save the inputs as well as the output, so you can check you're doing the right thing. Again, do this inIOand thenunsafePerformIOyourself out.