-- | 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
(b -> c
f . :: (b -> c) -> (a -> b) -> a -> c
. a -> b
g) a
x = b -> c
f (a -> b
g a
x)

infixr 9 .

-- | The mathematical symbol for function composition.
(∘) :: (b -> c) -> (a -> b) -> a -> c
∘ :: (b -> c) -> (a -> b) -> a -> c
(∘) = (b -> c) -> (a -> b) -> a -> c
forall b c a. (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
(c -> d
f .: :: (c -> d) -> (a -> b -> c) -> a -> b -> d
.: a -> b -> c
g) a
x b
y = c -> d
f (a -> b -> c
g a
x b
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
.* :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.*) = ((b -> c) -> b -> d) -> (a -> b -> c) -> a -> b -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (((b -> c) -> b -> d) -> (a -> b -> c) -> a -> b -> d)
-> ((c -> d) -> (b -> c) -> b -> d)
-> (c -> d)
-> (a -> b -> c)
-> a
-> b
-> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (c -> d) -> (b -> c) -> b -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.)

infixr 8 .*

(.**) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
.** :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
(.**) = ((b -> c -> d) -> b -> c -> e)
-> (a -> b -> c -> d) -> a -> b -> c -> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (((b -> c -> d) -> b -> c -> e)
 -> (a -> b -> c -> d) -> a -> b -> c -> e)
-> ((d -> e) -> (b -> c -> d) -> b -> c -> e)
-> (d -> e)
-> (a -> b -> c -> d)
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (d -> e) -> (b -> c -> d) -> b -> c -> e
forall c d a b. (c -> d) -> (a -> b -> c) -> a -> b -> d
(.*)

.*** :: (d -> e) -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e
(.***) = ((a -> b -> c -> d) -> a -> b -> c -> e)
-> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (((a -> b -> c -> d) -> a -> b -> c -> e)
 -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e)
-> ((d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e)
-> (d -> e)
-> (a -> a -> b -> c -> d)
-> a
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
forall d e a b c.
(d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
(.**)
.**** :: (d -> e)
-> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e
(.****) = ((a -> a -> b -> c -> d) -> a -> a -> b -> c -> e)
-> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (((a -> a -> b -> c -> d) -> a -> a -> b -> c -> e)
 -> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e)
-> ((d -> e) -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e)
-> (d -> e)
-> (a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (d -> e) -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e
forall d e a a b c.
(d -> e) -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e
(.***)
.***** :: (d -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.*****) = ((a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (((a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e)
 -> (a -> a -> a -> a -> b -> c -> d)
 -> a
 -> a
 -> a
 -> a
 -> b
 -> c
 -> e)
-> ((d -> e)
    -> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e)
-> (d -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (d -> e)
-> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e
forall d e a a a b c.
(d -> e)
-> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e
(.****)
.****** :: (d -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.******) = ((a -> a -> a -> a -> b -> c -> d)
 -> a -> a -> a -> a -> b -> c -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (((a -> a -> a -> a -> b -> c -> d)
  -> a -> a -> a -> a -> b -> c -> e)
 -> (a -> a -> a -> a -> a -> b -> c -> d)
 -> a
 -> a
 -> a
 -> a
 -> a
 -> b
 -> c
 -> e)
-> ((d -> e)
    -> (a -> a -> a -> a -> b -> c -> d)
    -> a
    -> a
    -> a
    -> a
    -> b
    -> c
    -> e)
-> (d -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (d -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.*****)
.******* :: (d -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.*******) = ((a -> a -> a -> a -> a -> b -> c -> d)
 -> a -> a -> a -> a -> a -> b -> c -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (((a -> a -> a -> a -> a -> b -> c -> d)
  -> a -> a -> a -> a -> a -> b -> c -> e)
 -> (a -> a -> a -> a -> a -> a -> b -> c -> d)
 -> a
 -> a
 -> a
 -> a
 -> a
 -> a
 -> b
 -> c
 -> e)
-> ((d -> e)
    -> (a -> a -> a -> a -> a -> b -> c -> d)
    -> a
    -> a
    -> a
    -> a
    -> a
    -> b
    -> c
    -> e)
-> (d -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (d -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.******)
.******** :: (d -> e)
-> (a -> a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.********) = ((a -> a -> a -> a -> a -> a -> b -> c -> d)
 -> a -> a -> a -> a -> a -> a -> b -> c -> e)
-> (a -> a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (((a -> a -> a -> a -> a -> a -> b -> c -> d)
  -> a -> a -> a -> a -> a -> a -> b -> c -> e)
 -> (a -> a -> a -> a -> a -> a -> a -> b -> c -> d)
 -> a
 -> a
 -> a
 -> a
 -> a
 -> a
 -> a
 -> b
 -> c
 -> e)
-> ((d -> e)
    -> (a -> a -> a -> a -> a -> a -> b -> c -> d)
    -> a
    -> a
    -> a
    -> a
    -> a
    -> a
    -> b
    -> c
    -> e)
-> (d -> e)
-> (a -> a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (d -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> 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 :: (b -> c) -> (a -> b) -> a -> c
compose1 = (b -> c) -> (a -> b) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.)

compose2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d
compose2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d
compose2 = (c -> d) -> (a -> b -> c) -> a -> b -> d
forall c d a b. (c -> d) -> (a -> b -> c) -> a -> b -> d
(.*)

compose3 :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
compose3 :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
compose3 = (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
forall d e a b c.
(d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
(.**)

compose4 :: (d -> e) -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e
compose4 = (d -> e) -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e
forall d e a a b c.
(d -> e) -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e
(.***)
compose5 :: (d -> e)
-> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e
compose5 = (d -> e)
-> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e
forall d e a a a b c.
(d -> e)
-> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e
(.****)
compose6 :: (d -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
compose6 = (d -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.*****)
compose7 :: (d -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
compose7 = (d -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.******)
compose8 :: (d -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
compose8 = (d -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.*******)
compose9 :: (d -> e)
-> (a -> a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
compose9 = (d -> e)
-> (a -> a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.********)

-- | 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
.:. :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
(.:.) = (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
forall d e a b c.
(d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
(.**)

.:: :: (d -> e) -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e
(.::) = (d -> e) -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e
forall d e a a b c.
(d -> e) -> (a -> a -> b -> c -> d) -> a -> a -> b -> c -> e
(.***)
.::. :: (d -> e)
-> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e
(.::.) = (d -> e)
-> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e
forall d e a a a b c.
(d -> e)
-> (a -> a -> a -> b -> c -> d) -> a -> a -> a -> b -> c -> e
(.****)
.::: :: (d -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.:::) = (d -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.*****)
.:::. :: (d -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.:::.) = (d -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.******)
.:::: :: (d -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.::::) = (d -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.*******)
.::::. :: (d -> e)
-> (a -> a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.::::.) = (d -> e)
-> (a -> a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
forall d e a a a a a a a b c.
(d -> e)
-> (a -> a -> a -> a -> a -> a -> a -> b -> c -> d)
-> a
-> a
-> a
-> a
-> a
-> a
-> a
-> b
-> c
-> e
(.********)

infixr 8 .:.
infixr 8 .::
infixr 8 .::.
infixr 8 .:::
infixr 8 .:::.
infixr 8 .::::
infixr 8 .::::.