
#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