[GHC] #15143: Passing an IO value through several functions results in program hanging.

GHC ghc-devs at haskell.org
Thu May 17 22:17:23 UTC 2018


#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


More information about the ghc-tickets mailing list