
#15143: Passing an IO value through several functions results in program hanging. -------------------------------------+------------------------------------- Reporter: Burtannia | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.6.1 Component: Compiler | Version: 8.4.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Runtime | Unknown/Multiple performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Why do you think this is a bug? You are compputing {{{ incTime (incTime ( ... (incTime testObs) ... )) }}} where {{{ incTime :: IO Obs -> IO Obs incTime o = do obs <- o case obs of ObsTime t -> return $ ObsTime (t+1) _ -> o }}} Each call of `incTime` invokes its argument `o` twice. Since `o` is passed in as an argument, GHC ''must'' call it twice in case it has side effects. The alternative code {{{ incTime' o = do obs <- o case obs of ObsTime t -> return $ ObsTime (t+1) _ -> return obs }}} is not semantically equivalent. Imagine called {{{ incTime (do { updRef r (+ 1); return ObsTemp }) }}} then I expect the reference `r` to be incremented twice. But `incTime'` will only increment it once. So each call to `incTime o` calls `o` twice. But in the call `incTime (incTime o)`, we call `incTime o` twice; and each call calls `o` twice. Result: four calls to `o`. If the nest is 3 deep we get eigth calls and so on. In short, this program has exponential runtime ''by design'', and GHC faithfully does what you ask. In short, it looks fine to me. Do you agree? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15143#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler