Re: #16357: Add `oneShot` to the implementation of foldlM

"GHC" <[email protected]>
Newsgroups gmane.comp.lang.haskell.glasgow.bugs
Message-ID <[email protected]>
#16357: Add `oneShot` to the implementation of foldlM
-------------------------------------+-------------------------------------
        Reporter:  autotaker         |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  libraries/base    |              Version:  8.9
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by autotaker):

 This bug is caused by INLINE annotation for `c` which is introduced while
 fixing #8763.

 After list fusion, the example program would be:
 {{{#!hs
 f (I# n) =
   letrec go i =
         case i `remInt#` 2 of
            1# -> case i ==# n of
              0# -> go (i +# 1)
              1# -> pure
            0# -> c (I# i) (case i ==# n of
              0# -> go (i +# 1)
              1# -> pure)
   in go 0# (I# 0)
 c x k z = k $! (z + x)
 {-# INLINE c #-}
 }}}
 We can see function `c` is lifted to the **top-level definition**.
 Besides, the continuation `case i ==# n of { 0# -> go (i +# 1); 1# -> pure
 }`
 is passed as a **higher-order** argument of `c`.
 Therefore, CallArity analyzer cannot find the correct call-arity of
 function `go`.

 Without INLINE pragma for `c`, we have:
 {{{#!hs
 f (I# n) =
   letrec go i =
         case i `remInt#` 2 of
            1# -> case i ==# n of
              0# -> go (i +# 1)
              1# -> pure
            0# ->
              let k = case i ==# n of
                      0# -> go (i +# 1)
                      1# -> pure in
              \z -> k $! I# (z + (I# i))
   in go 0# (I# 0)
 }}}
 We can see the continuation `k` is defined inside `go`.
 In this case, CallArity works good and finds the call-arity of `go` as 3
 (not 2 because it includes `State# Realworld`).

 If we define `c x k = \z -> f z x >>= k` (instead of `c x k z = f z x >>=
 k`) and add an INLINE pragma for `c`,
 CallArity works good because the continuation is defined inside `go`.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/16357#comment:2>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.