module Control.Composition
    ( -- * Postcomposition
      (.*)
    , (.**)
    , (.***)
    , (.****)
    , (.*****)
    , (.******)
    -- * Precomposition
    , (-.)
    , (.@)
    , (.@@)
    , (.@@@)
    , (.@@@@)
    , (.@@@@@)
    -- * Monadic postcomposition
    , (<=*<)
    , (<=**<)
    , (>=**>)
    , (>=*>)
    -- * Monadic precomposition
    , (<-=*<)
    , (>-=*>)
    , (<-=**<)
    , (>-=**>)
    -- * Between combinators
    , between
    , (~@~)
    , betweenM
    , (<~@~<)
    -- * Fancy function application
    , (-$)
    -- * Monadic helpers
    , bisequence'
    , (.$)
    -- * Monadic actions
    , axe
    , biaxe
    -- * Composition with lists of functions
    , thread
    , threadM
    -- * Tuple helpers
    , both
    , dup
    , (+>)
    -- * J inspired
    , (&:)
    -- * Reëxports from base
    , (<=<)
    , (>=>)
    , (<**>)
    , (&)
    , (<&>)
    , fix
    , on
    ) where

import           Control.Applicative
import           Control.Arrow       ((***))
import           Control.Monad
import           Data.Foldable
import           Data.Function       (fix, on, (&))
import           Data.Functor        ((<&>))
import           Data.Traversable
import           Prelude             hiding (foldr)

infixr 8 .*
infixr 8 .**
infixr 8 .***
infixr 8 .****
infixr 8 .*****
infixr 8 .******
infixr 8 -.
infixr 8 .@
infixr 8 .@@
infixr 8 .@@@
infixr 8 .@@@@
infixr 8 .@@@@@
infixl 0 &:
infixl 3 .$
infixl 8 -$
infixl 8 ~@~
infixl 8 <~@~<
infixr 1 <=*<
infixr 1 >=*>
infixr 1 <=**<
infixr 1 >=**>
infixr 1 <-=*<
infixr 1 >-=*>
infixr 1 <-=**<
infixr 1 >-=**>
infixr 6 +>

axe :: (Traversable t, Applicative f) => t (a -> f ()) -> a -> f ()
axe :: t (a -> f ()) -> a -> f ()
axe = t (f ()) -> f ()
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Applicative f) =>
t (f a) -> f ()
sequenceA_ (t (f ()) -> f ())
-> (t (a -> f ()) -> a -> t (f ())) -> t (a -> f ()) -> a -> f ()
forall c d a b. (c -> d) -> (a -> b -> c) -> a -> b -> d
.* t (a -> f ()) -> a -> t (f ())
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA

bisequence' :: (Traversable t, Applicative f) => t (a -> b -> f c) -> a -> b -> t (f c)
bisequence' :: t (a -> b -> f c) -> a -> b -> t (f c)
bisequence' = t (b -> f c) -> b -> t (f c)
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA (t (b -> f c) -> b -> t (f c))
-> (t (a -> b -> f c) -> a -> t (b -> f c))
-> t (a -> b -> f c)
-> a
-> b
-> t (f c)
forall c d a b. (c -> d) -> (a -> b -> c) -> a -> b -> d
.* t (a -> b -> f c) -> a -> t (b -> f c)
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA

biaxe :: (Traversable t, Applicative f) => t (a -> b -> f ()) -> a -> b -> f ()
biaxe :: t (a -> b -> f ()) -> a -> b -> f ()
biaxe = t (f ()) -> f ()
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Applicative f) =>
t (f a) -> f ()
sequenceA_ (t (f ()) -> f ())
-> (t (a -> b -> f ()) -> a -> b -> t (f ()))
-> t (a -> b -> f ())
-> a
-> b
-> f ()
forall d e a b c.
(d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
.** t (a -> b -> f ()) -> a -> b -> t (f ())
forall (t :: * -> *) (f :: * -> *) a b c.
(Traversable t, Applicative f) =>
t (a -> b -> f c) -> a -> b -> t (f c)
bisequence'

-- | Pronounced \'appose\'. Synonym for 'on'
--
-- @since 3.0.0.0
(&:) :: (b -> b -> c) -> (a -> b) -> a -> a -> c
&: :: (b -> b -> c) -> (a -> b) -> a -> a -> c
(&:) = (b -> b -> c) -> (a -> b) -> a -> a -> c
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on

-- | Infix synonym for 'both'
--
-- @since 3.0.0.0
(+>) :: (a -> b) -> (a, a) -> (b, b)
+> :: (a -> b) -> (a, a) -> (b, b)
(+>) = (a -> b) -> (a, a) -> (b, b)
forall a b. (a -> b) -> (a, a) -> (b, b)
both

both :: (a -> b) -> (a, a) -> (b, b)
both :: (a -> b) -> (a, a) -> (b, b)
both = ((a -> b) -> (a -> b) -> (a, a) -> (b, b))
-> (a -> b) -> (a, a) -> (b, b)
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (a -> b) -> (a -> b) -> (a, a) -> (b, b)
forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
(***)

-- | @since 2.0.1.0
dup :: a -> (a, a)
dup :: a -> (a, a)
dup = (a -> a -> (a, a)) -> a -> (a, a)
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (,)

-- | Infix version of 'join'
--
-- As an example, one could use this to rewrite
--
-- > between (char '"') (char '"')
--
-- to
--
-- > between .$ (char '"')
--
-- Or
--
-- > fromEither :: Either a a -> a
-- > fromEither = either id id
--
-- to
--
-- > fromEither :: Either a a -> a
-- > fromEither = either .$ id
--
-- @since 2.0.2.0
(.$) :: Monad m => m (m a) -> m a
.$ :: m (m a) -> m a
(.$) = m (m a) -> m a
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join

-- | Backwards function application. This is an infix synonym for 'flip'
(-$) :: (a -> b -> c) -> b -> a -> c
-$ :: (a -> b -> c) -> b -> a -> c
(-$) = (a -> b -> c) -> b -> a -> c
forall a b c. (a -> b -> c) -> b -> a -> c
flip

(.*) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
.* :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.*) c -> d
f a -> b -> c
g = \a
x b
y -> c -> d
f (a -> b -> c
g a
x b
y)

(.**) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
.** :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
(.**) d -> e
f a -> b -> c -> d
g = \a
x b
y c
z -> d -> e
f (a -> b -> c -> d
g a
x b
y c
z)

(.***) :: (e -> f) -> (a -> b -> c -> d -> e) -> a -> b -> c -> d -> f
.*** :: (e -> f) -> (a -> b -> c -> d -> e) -> a -> b -> c -> d -> f
(.***) e -> f
f a -> b -> c -> d -> e
g = \a
w b
x c
y d
z -> e -> f
f (a -> b -> c -> d -> e
g a
w b
x c
y d
z)

-- | @since 1.0.0.0
(.****) :: (f -> g) -> (a -> b -> c -> d -> e -> f) -> a -> b -> c -> d -> e -> g
.**** :: (f -> g)
-> (a -> b -> c -> d -> e -> f) -> a -> b -> c -> d -> e -> g
(.****) f -> g
f a -> b -> c -> d -> e -> f
g = \a
v b
w c
x d
y e
z -> f -> g
f (a -> b -> c -> d -> e -> f
g a
v b
w c
x d
y e
z)

-- | @since 2.0.5.0
(.*****) :: (g -> h) -> (a -> b -> c -> d -> e -> f -> g) -> a -> b -> c -> d -> e -> f -> h
.***** :: (g -> h)
-> (a -> b -> c -> d -> e -> f -> g)
-> a
-> b
-> c
-> d
-> e
-> f
-> h
(.*****) g -> h
f a -> b -> c -> d -> e -> f -> g
g = \a
u b
v c
w d
x e
y f
z -> g -> h
f (a -> b -> c -> d -> e -> f -> g
g a
u b
v c
w d
x e
y f
z)

-- | @since 2.0.5.0
(.******) :: (h -> i) -> (a -> b -> c -> d -> e -> f -> g -> h) -> a -> b -> c -> d -> e -> f -> g -> i
.****** :: (h -> i)
-> (a -> b -> c -> d -> e -> f -> g -> h)
-> a
-> b
-> c
-> d
-> e
-> f
-> g
-> i
(.******) h -> i
f a -> b -> c -> d -> e -> f -> g -> h
g = \a
t b
u c
v d
w e
x f
y g
z -> h -> i
f (a -> b -> c -> d -> e -> f -> g -> h
g a
t b
u c
v d
w e
x f
y g
z)

-- | A monadic version of '.*'. Compare '<=<'.
--
-- As an example, one could use this to rewrite
--
-- > \x y z -> f (g x y z) z
--
-- to
--
-- > f <=*< g
--
-- @since 1.5.2.0
(<=*<) :: Monad m => (c -> m d) -> (a -> b -> m c) -> a -> b -> m d
<=*< :: (c -> m d) -> (a -> b -> m c) -> a -> b -> m d
(<=*<) c -> m d
f a -> b -> m c
g = \a
x b
y -> c -> m d
f (c -> m d) -> m c -> m d
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< a -> b -> m c
g a
x b
y

-- | The bleeding fish operator
--
-- @since 1.5.2.0
(<=**<) :: Monad m => (d -> m e) -> (a -> b -> c -> m d) -> a -> b -> c -> m e
<=**< :: (d -> m e) -> (a -> b -> c -> m d) -> a -> b -> c -> m e
(<=**<) d -> m e
f a -> b -> c -> m d
g = \a
x b
y c
z -> d -> m e
f (d -> m e) -> m d -> m e
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< a -> b -> c -> m d
g a
x b
y c
z

-- | Compare '>=>'.
--
-- @since 1.5.2.0
(>=*>) :: Monad m => (a -> b -> m c) -> (c -> m d) -> a -> b -> m d
>=*> :: (a -> b -> m c) -> (c -> m d) -> a -> b -> m d
(>=*>) a -> b -> m c
g c -> m d
f = \a
x b
y -> c -> m d
f (c -> m d) -> m c -> m d
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< a -> b -> m c
g a
x b
y

-- | @since 1.5.2.0
(>=**>) :: Monad m => (a -> b -> c -> m d) -> (d -> m e) -> a -> b -> c -> m e
>=**> :: (a -> b -> c -> m d) -> (d -> m e) -> a -> b -> c -> m e
(>=**>) a -> b -> c -> m d
g d -> m e
f = \a
x b
y c
z -> d -> m e
f (d -> m e) -> m d -> m e
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< a -> b -> c -> m d
g a
x b
y c
z

-- | @since 1.5.2.0
(<-=*<) :: Monad m => (b -> m c) -> (a -> c -> m d) -> a -> b -> m d
<-=*< :: (b -> m c) -> (a -> c -> m d) -> a -> b -> m d
(<-=*<) b -> m c
f a -> c -> m d
g = \a
x b
y -> a -> c -> m d
g a
x (c -> m d) -> m c -> m d
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< b -> m c
f b
y

-- | @since 1.5.2.0
(>-=*>) :: Monad m => (a -> c -> m d) -> (b -> m c) -> a -> b -> m d
>-=*> :: (a -> c -> m d) -> (b -> m c) -> a -> b -> m d
(>-=*>) a -> c -> m d
g b -> m c
f = \a
x b
y -> a -> c -> m d
g a
x (c -> m d) -> m c -> m d
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< b -> m c
f b
y

-- | @since 1.5.2.0
(<-=**<) :: Monad m => (c -> m d) -> (a -> b -> d -> m e) -> a -> b -> c -> m e
<-=**< :: (c -> m d) -> (a -> b -> d -> m e) -> a -> b -> c -> m e
(<-=**<) c -> m d
f a -> b -> d -> m e
g = \a
x b
y c
z -> a -> b -> d -> m e
g a
x b
y (d -> m e) -> m d -> m e
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< c -> m d
f c
z

-- | @since 1.5.2.0
(>-=**>) :: Monad m => (a -> b -> d -> m e) -> (c -> m d) -> a -> b -> c -> m e
>-=**> :: (a -> b -> d -> m e) -> (c -> m d) -> a -> b -> c -> m e
(>-=**>) a -> b -> d -> m e
g c -> m d
f = \a
x b
y c
z -> a -> b -> d -> m e
g a
x b
y (d -> m e) -> m d -> m e
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< c -> m d
f c
z

-- | @since 2.0.3.0
(.@) :: (b -> c) -> (a -> c -> d) -> a -> b -> d
.@ :: (b -> c) -> (a -> c -> d) -> a -> b -> d
(.@) b -> c
f a -> c -> d
g = \a
x b
y -> a -> c -> d
g a
x (b -> c
f b
y)

-- | @since 2.0.3.0
(.@@) :: (c -> d) -> (a -> b -> d -> e) -> a -> b -> c -> e
.@@ :: (c -> d) -> (a -> b -> d -> e) -> a -> b -> c -> e
(.@@) c -> d
f a -> b -> d -> e
g = \a
x b
y c
z -> a -> b -> d -> e
g a
x b
y (c -> d
f c
z)

-- | @since 2.0.3.0
(.@@@) :: (d -> e) -> (a -> b -> c -> e -> f) -> a -> b -> c -> d -> f
.@@@ :: (d -> e) -> (a -> b -> c -> e -> f) -> a -> b -> c -> d -> f
(.@@@) d -> e
f a -> b -> c -> e -> f
g = \a
w b
x c
y d
z -> a -> b -> c -> e -> f
g a
w b
x c
y (d -> e
f d
z)

-- | @since 2.0.3.0
(.@@@@) :: (e -> f) -> (a -> b -> c -> d -> f -> g) -> a -> b -> c -> d -> e -> g
.@@@@ :: (e -> f)
-> (a -> b -> c -> d -> f -> g) -> a -> b -> c -> d -> e -> g
(.@@@@) e -> f
f a -> b -> c -> d -> f -> g
g = \a
v b
w c
x d
y e
z -> a -> b -> c -> d -> f -> g
g a
v b
w c
x d
y (e -> f
f e
z)

-- | @since 3.0.0.0
(.@@@@@) :: (f -> g) -> (a -> b -> c -> d -> e -> g -> h) -> a -> b -> c -> d -> e -> f -> h
.@@@@@ :: (f -> g)
-> (a -> b -> c -> d -> e -> g -> h)
-> a
-> b
-> c
-> d
-> e
-> f
-> h
(.@@@@@) f -> g
f a -> b -> c -> d -> e -> g -> h
g = \a
u b
v c
w d
x e
y f
z -> a -> b -> c -> d -> e -> g -> h
g a
u b
v c
w d
x e
y (f -> g
f f
z)

-- | Backwards function composition. This is a specialization of '<&>', but it
-- has a different fixity.
(-.) :: (a -> b) -> (b -> c) -> a -> c
-. :: (a -> b) -> (b -> c) -> a -> c
(-.) = (a -> b) -> (b -> c) -> a -> c
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
(<&>)

-- infixl 1
-- (.&) :: a -> b -> (a -> b -> c) -> c
--
-- infixr 0
-- (.$) :: (a -> b -> c) -> a -> b -> c

-- | @since 1.1.0.1
thread :: Foldable t => t (a -> a) -> a -> a
thread :: t (a -> a) -> a -> a
thread = ((a -> a) -> (a -> a) -> a -> a)
-> (a -> a) -> t (a -> a) -> a -> a
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) a -> a
forall a. a -> a
id
{-# INLINE thread #-}

threadM :: (Monad m, Foldable t, Applicative m) => t (a -> m a) -> a -> m a
threadM :: t (a -> m a) -> a -> m a
threadM = ((a -> m a) -> (a -> m a) -> a -> m a)
-> (a -> m a) -> t (a -> m a) -> a -> m a
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (a -> m a) -> (a -> m a) -> a -> m a
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
(<=<) a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
{-# INLINE threadM #-}

-- | Can be used to rewrite
--
-- > \g -> f . g . h
--
-- to
--
-- > between f h
--
-- @since 1.5.3.0
between :: (c -> d) -> (a -> b) -> (b -> c) -> a -> d
between :: (c -> d) -> (a -> b) -> (b -> c) -> a -> d
between c -> d
f a -> b
g = (c -> d
f (c -> d) -> (a -> c) -> a -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((a -> c) -> a -> d) -> ((b -> c) -> a -> c) -> (b -> c) -> a -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b -> c) -> (a -> b) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
g)

-- @since 1.5.3.0
betweenM :: Monad m => (c -> m d) -> (a -> m b) -> (b -> m c) -> a -> m d
betweenM :: (c -> m d) -> (a -> m b) -> (b -> m c) -> a -> m d
betweenM c -> m d
f a -> m b
g = (c -> m d
f (c -> m d) -> (a -> m c) -> a -> m d
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=<) ((a -> m c) -> a -> m d)
-> ((b -> m c) -> a -> m c) -> (b -> m c) -> a -> m d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b -> m c) -> (a -> m b) -> a -> m c
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< a -> m b
g)

-- @since 1.5.3.0
(~@~) :: (c -> d) -> (a -> b) -> (b -> c) -> a -> d
~@~ :: (c -> d) -> (a -> b) -> (b -> c) -> a -> d
(~@~) = (c -> d) -> (a -> b) -> (b -> c) -> a -> d
forall c d a b. (c -> d) -> (a -> b) -> (b -> c) -> a -> d
between

-- @since 1.5.3.0
(<~@~<) :: Monad m => (c -> m d) -> (a -> m b) -> (b -> m c) -> a -> m d
<~@~< :: (c -> m d) -> (a -> m b) -> (b -> m c) -> a -> m d
(<~@~<) = (c -> m d) -> (a -> m b) -> (b -> m c) -> a -> m d
forall (m :: * -> *) c d a b.
Monad m =>
(c -> m d) -> (a -> m b) -> (b -> m c) -> a -> m d
betweenM