The key here is to maintain the programmer aware that it is not pure, but there are no IO and that the results have no meaning from session to session.
Instance Monad Transient where
Transient x ↠ f = f x
return x = Transient x
We can Transient`ize IO calls by means of an implicit memoization:
liftT:: IO a -> Transient a
liftT= < whatever memoization code>
liftT2=....
liftT3=....
Memorization then is embedded in the monad transformation
This may be more elegant than IO plus unsafePerformIO and is more informative for the programmer. The transition form IO to pure can be done in two steps, see below
Instead of unsafePerformIO, we can use: