-- | 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. module Data.Composition ( -- * Math (∘) -- * Colons and dots , (.:) , (.:.) , (.::) , (.::.) , (.:::) , (.:::.) , (.::::) , (.::::.) -- * Asterisks , (.*) , (.**) , (.***) , (.****) , (.*****) , (.******) , (.*******) , (.********) -- * composeN , compose1 , compose2 , compose3 , compose4 , compose5 , compose6 , compose7 , compose8 , compose9 ) where -- Not exported. This is defined here to remove the dependency on base (.) :: (b -> c) -> (a -> b) -> a -> c (f . g) x = f (g x) infixr 9 . -- | The mathematical symbol for function composition. (∘) :: (b -> c) -> (a -> b) -> a -> c (∘) = (.) infixr 9 ∘ -- | Compose two functions. @f .: g@ is similar to @f . g@ -- except that @g@ will be fed /two/ arguments instead of one -- before handing its result to @f@. -- -- This function is defined as -- -- > (f .: g) x y = f (g x y) -- -- Example usage: -- -- > concatMap :: (a -> b) -> [a] -> [b] -- > concatMap = concat .: map -- -- Notice how /two/ arguments -- (the function /and/ the list) -- will be given to @map@ before the result -- is passed to @concat@. This is equivalent to: -- -- > concatMap f xs = concat (map f xs) (.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d (f .: g) x y = f (g x y) infixr 8 .: -- | Equivalent to '.:' -- -- The pattern of appending asterisks is -- straightforward to extend to similar functions: -- (compose2 = .*, compose3 = .**, etc). -- However, @.:@ has been commonly adopted amongst Haskellers, -- and the need for compose3 and beyond is rare in practice. (.*) :: (c -> d) -> (a -> b -> c) -> a -> b -> d (.*) = (.) . (.) infixr 8 .* (.**) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e (.**) = (.) . (.*) (.***) = (.) . (.**) (.****) = (.) . (.***) (.*****) = (.) . (.****) (.******) = (.) . (.*****) (.*******) = (.) . (.******) (.********) = (.) . (.*******) infixr 8 .** infixr 8 .*** infixr 8 .**** infixr 8 .***** infixr 8 .****** infixr 8 .******* infixr 8 .******** -- | @composeN f g@ means give @g@ @N@ inputs -- and then pass its result to @f@. compose1 :: (b -> c) -> (a -> b) -> a -> c compose1 = (.) compose2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d compose2 = (.*) compose3 :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e compose3 = (.**) compose4 = (.***) compose5 = (.****) compose6 = (.*****) compose7 = (.******) compose8 = (.*******) compose9 = (.********) -- | One compact pattern for composition operators is to -- "count the dots after the first one", -- which begins with the common '.:', and proceeds by first -- appending another @.@ and then replacing it with @:@ (.:.) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e (.:.) = (.**) (.::) = (.***) (.::.) = (.****) (.:::) = (.*****) (.:::.) = (.******) (.::::) = (.*******) (.::::.) = (.********) infixr 8 .:. infixr 8 .:: infixr 8 .::. infixr 8 .::: infixr 8 .:::. infixr 8 .:::: infixr 8 .::::.