For some reason I need to trick Haskell into executing an infinite loop rather than just detecting it and exiting with <<loop>>
, but it's too smart to do it. Are there any handy examples where a loop is caused by a strictness annotation (!
), or can I turn off the loop detection? Currently I'm doing
x = x + y
y = x + y
inf !n = 0
main = do
print $ inf x
This should do it:
{-# LANGUAGE BangPatterns #-}
f :: Int -> Int
f x = if x >= 0 then f (x + 1) else 0
fun !n = 0
main = print $ fun $ f 0
GHC does indeed seem to be pretty clever at spotting the loop, before I added the if
it even spotted the recursive function call.
I've tested this with -O3
on GHC 7.10.
EDIT: added the extra function fun
as suggested by the asker, just to satisfy the requirement that a bang pattern be involved. It's not really relevant to the loop itself. Also changed from Integer
to Int
as suggested by another answer, to ensure constant memory usage.
The "problem" is that while ghc is evaluating a thunk, it replaces it with a blackhole. That's why something like the following simple example would not work:
inf :: ()
inf = inf
main :: IO ()
main = return $! inf
Ghc will force inf, that will cause it to force inf a second time. It will realize inf has been blackholed and detect a loop.
The solution proposed of an infinite counter will work, but will allocate more and more memory for the integer counter. It probably doesn't matter, since the memory for an Integer is logarithmic, but it might be slightly more elegant to use an Int and just let the counter wrap.
Another option would be to use an infinite data structure. That will create garbage, but in steady state consume a fixed amount of allocated memory. Something like:
main :: IO ()
main = return $! last $ repeat ()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With