[GHC] #7994: Make foldl into a good consumer

GHC ghc-devs at haskell.org
Fri Jan 24 16:17:40 UTC 2014


#7994: Make foldl into a good consumer
-------------------------------------+------------------------------------
        Reporter:  simonpj           |            Owner:
            Type:  bug               |           Status:  new
        Priority:  normal            |        Milestone:
       Component:  Compiler          |          Version:  7.6.3
      Resolution:                    |         Keywords:
Operating System:  Unknown/Multiple  |     Architecture:  Unknown/Multiple
 Type of failure:  None/Unknown      |       Difficulty:  Unknown
       Test Case:                    |       Blocked By:
        Blocking:                    |  Related Tickets:
-------------------------------------+------------------------------------

Comment (by nomeata):

 Ok, here is a very different approach to solving the original problem of
 this ticket, namely making `foldl` a good consumer.

 Instead of trying hard to make the compiler sufficiently smart, why not
 help him a little bit? So here is what I did:

 I created a new magic function `oneShot` (similar to `lazy` etc.).
 Semantically, `oneShot = λ f λ x. f x", but the unfolding will put a
 `OneShot` on the binder for x. So essentially, it allows the programmer to
 tell the compiler: I promise I will only call this function once (and if I
 break my promise, I won’t blame you).

 So now one would define
 {{{
 foldl k z xs = foldr (\v fn -> oneShot (\z -> fn (k z v))) id xs z
 }}}
 (because at this point, we know that the result of `foldr ... id xs` is
 ''not'' going to be used multiple times) and voilà – good code:

 {{{
 Foo.$wfoo
   :: GHC.Prim.Int# -> (# GHC.Types.Double, GHC.Types.Double #)
 [GblId,
  Arity=1,
  Str=DmdType <L,U>,
  Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=1, Value=True,
          ConLike=True, WorkFree=True, Expandable=True,
          Guidance=IF_ARGS [0] 249 30}]
 Foo.$wfoo =
   \ (ww_s1ox :: GHC.Prim.Int#) ->
     case GHC.Prim.tagToEnum# @ GHC.Types.Bool (GHC.Prim.># 1 ww_s1ox)
     of _ [Occ=Dead] {
       GHC.Types.False ->
         letrec {
           $wgo_s1ot [Occ=LoopBreaker]
             :: GHC.Prim.Int#
                -> GHC.Prim.Double#
                -> GHC.Prim.Double#
                -> (# GHC.Types.Double, GHC.Types.Double #)
           [LclId, Arity=3, Str=DmdType <S,U><L,U><L,U>]
           $wgo_s1ot =
             \ (w_s1oc :: GHC.Prim.Int#)
               (ww1_s1oj :: GHC.Prim.Double#)
               (ww2_s1oo :: GHC.Prim.Double#) ->
               case Foo.f (GHC.Types.I# w_s1oc)
               of _ [Occ=Dead] { Data.Complex.:+ ww8_aYl ww9_aYm ->
               case ww8_aYl of _ [Occ=Dead] { GHC.Types.D# ww11_s1sa ->
               case ww9_aYm of _ [Occ=Dead] { GHC.Types.D# ww13_s1sc ->
               case GHC.Prim.tagToEnum#
                      @ GHC.Types.Bool (GHC.Prim.==# w_s1oc ww_s1ox)
               of _ [Occ=Dead] {
                 GHC.Types.False ->
                   $wgo_s1ot
                     (GHC.Prim.+# w_s1oc 1)
                     (GHC.Prim.+## ww1_s1oj ww11_s1sa)
                     (GHC.Prim.+## ww2_s1oo ww13_s1sc);
                 GHC.Types.True ->
                   (# GHC.Types.D# (GHC.Prim.+## ww1_s1oj ww11_s1sa),
                      GHC.Types.D# (GHC.Prim.+## ww2_s1oo ww13_s1sc) #)
               }
               }
               }
               }; } in
         $wgo_s1ot 1 0.0 0.0;
       GHC.Types.True -> (# Foo.foo1, Data.Complex.$fFloatingComplex1 #)
     }
 }}}

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/7994#comment:7>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list