Reputation: 1736
keepRunning <- newIORef True
let loop = do
running <- readIORef keepRunning
if running then
do
{- Do stuff -}
loop running
return ()
else
do
{- Do stuff -}
return ()
let keepRunning = True
let loop running = if running then
do
{- Do stuff -}
loop running
return ()
else do
{- Do stuff -}
return ()
loop keepRunning
Is there any reason to prefer one of the above methods above the other? Will the do
blocks containing recursion slow the program down compared to outside the do block? If you can replace every instance of Data.IORef
with a function, then why does Data.IORef
even exist?
Upvotes: 0
Views: 138
Reputation: 370415
If your {- Do stuff -}
in your first version directly assigns keepRunning
to the result of some computation, you can of course rewrite it easily to make that computation the condition for the recursion and get rid of the IORef
. That would be the preferable solution.
However, if your first version sets keepRunning
inside some other function, the equivalent ref-less version could become quite a bit more complicated. So which version is preferable would be less clear in that case. Though you could make the point that such a thing would be bad design in the first place. It's hard to say anything specific without knowing what {- Do stuff -}
actually does.
Will the do blocks containing recursion slow the program down compared to outside the do block?
No.
If you can replace every instance of Data.IORef with a function, then why does Data.IORef even exist?
Depending on the APIs you work with, you might not be able to (say you have event handlers in a non-FRP GUI library). Further there are cases where you could remove IORef, but only by hurting performance and/or making code more complicated.
That said your example of using an IORef
as a loop condition is one where you could almost certainly write a better version without IORef
.
Upvotes: 3