
On Fri, Aug 19, 2016 at 11:50 AM, Joachim Breitner
Hi,
Am Freitag, den 19.08.2016, 11:16 -0700 schrieb Theodore Lief Gannon:
Well... there's that rather worrisome introductory paragraph of the Data.Composition docs, though:
"This module is for convenience and demonstrative purposes more than it is for providing actual value. I do not recommend that you rely on this module for performance-sensitive code. Because this module is not based on Prelude's (.), some chances at optimization might be missed by your compiler."
I wonder if that is really something to worry about. Prelude’s (.) is not special in any way:
Yes and no. Prelude's (.) is not special in that GHC doesn't identify it as something that must be treated differently from what's expected from the definition (as opposed to, say, ($)). However, (.) is inherently a special case because of performance issues about closures. For example, whether we define: (.) f g = \x -> f (g x) vs: (.) f g x = f (g x) has ramifications, though it's fairly easy to guess which one of those two will be most performant. However, it's much less clear which of the following definitions will be the most performant: (.:) = (.) . (.) (.:) f g = (f .) . g (.:) f g = \x y -> f (g x y) For the version implemented in pointless-fun:Data.Function.Pointless, I actually did some benchmarking to determine which was fastest. It is (a) faster by a surprisingly large margin, and (b) not the one I expected to be the fastest. I haven't run those benchmarks on the latest versions of GHC, but that just underscores the point. Because the performance difference is significant and unexpected, having a single blessed (and maintained!) definition would be beneficial to anyone who actually uses this function in production code— whether that blessed definition is in base or some other library everyone has and knows about. -- Live well, ~wren