<div dir="ltr">(#.) :: Coercible b c => (b -> c) -> (a -> b) -> (a -> c)<div>(#.) _ = coerce</div><div>{-# INLINE (#.) #-}</div><div><br></div><div>(.#) :: Coercible a b => (b -> c) -> (a -> b) -> (a -> c)</div><div>(.#) f _ = coerce f</div><div>{-# INLINE (.#) #-}</div><div><br></div><div>The first of these is exported from Data.Functor.Util, and used in many places inside of base for efficiency over '.' (compose), However no module in base actually exports these. I have recently been using Data.Coerce more frequently and think it would be useful to go ahead and export these from somewhere in base.</div><div><br></div><div>For convenience, I will paste the note about (#.) from Data.Functor.Util:</div><div><br></div><div>"Note [Function coercion]</div><div>~~~~~~~~~~~~~~~~~~~~~~~</div><div><br></div><div>Several functions here use (#.) instead of (.) to avoid potential efficiency</div><div>problems relating to #7542. The problem, in a nutshell:</div><div><br></div><div>If N is a newtype constructor, then N x will always have the same</div><div>representation as x (something similar applies for a newtype deconstructor).</div><div>However, if f is a function,</div><div><br></div><div>N . f = \x -> N (f x)</div><div><br></div><div>This looks almost the same as f, but the eta expansion lifts it--the lhs could</div><div>be _|_, but the rhs never is. This can lead to very inefficient code.  Thus we</div><div>steal a technique from Shachaf and Edward Kmett and adapt it to the current</div><div>(rather clean) setting. Instead of using  N . f,  we use  N #. f, which is</div><div>just</div><div><br></div><div>coerce f `asTypeOf` (N . f)</div><div><br></div><div>That is, we just *pretend* that f has the right type, and thanks to the safety</div><div>of coerce, the type checker guarantees that nothing really goes wrong. We still</div><div>have to be a bit careful, though: remember that #. completely ignores the</div><div>*value* of its left operand.</div><div>"</div></div>