[GHC] #15131: Speed up certain Foldable NonEmpty methods

GHC ghc-devs at haskell.org
Wed May 9 10:41:11 UTC 2018


#15131: Speed up certain Foldable NonEmpty methods
-------------------------------------+-------------------------------------
        Reporter:  dfeuer            |                Owner:  (none)
            Type:  bug               |               Status:  patch
        Priority:  normal            |            Milestone:  8.6.1
       Component:  Core Libraries    |              Version:  8.2.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):  Phab:D4677
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by YitzGale):

 I just gave one or two examples in the reddit thread, but really all the
 methods need review.

 I'm not convinced about the default {{length}} being better. Perhaps
 switch the order, {{List.length as + 1}}. Does GHC not inline primitive
 {{+}}? And you do an extra {{+0}}. But if I'm wrong, the clear explanatory
 comment is highly appreciated.

 Why not just put the obvious trivial explicit implementation for every
 method? It would make the code cleaner and easier to read, without having
 to look up the default and then scratch your head about what gets
 optimized.

 Note that for historical reasons several methods for List are still
 implemented via {{foldl}}. That is in very rare cases better than
 {{foldl'}}, in many cases the same because GHC optimizes it, and in some
 cases worse. My opinion is that {{NonEmpty}} should always behave the same
 as {{List}}, whatever that may be. It's worth it to add one extra
 operation to the {{NonEmpty}} implementation so that we can refer to the
 List implementation and not hard-code a copy of it.

 Here's my alternative "patch" (sorry I don't know how to offer an
 alternative patch on Phab):

 {{{
 #!haskell
 instance Foldable NonEmpty where
     elem x (a :| as) = x == a || x `List.elem` as
     foldl f z ~(a :| as) = List.foldl f (f z a) as
     foldl' f z ~(a :| as) = let z' = f z a in z' `seq` foldl' f z' as
     foldl1 f ~(a :| as) = List.foldl f a as
     foldr f z ~(a :| as) = f a (List.foldr f z as)
     foldr1 f ~(a :| as) = List.foldr f a as
     foldMap f ~(a :| as) = f a `mappend` foldMap f as
     fold ~(m :| ms) = m `mappend` fold ms
     length (_ :| as) = List.length as + 1
     maximum (a :| as) = max a (List.maximum as)
     minimum (a :| as) = min a (List.minimum as)
     null _ = False
     product (a :| as) = a * List.product as
     sum (a :| as) = a + List.sum as
     toList (a :| as) = a : as

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


More information about the ghc-tickets mailing list