module Control.Arrow.Extras where

import Control.Arrow

-- | Feed the output of second arrow into the output of the first arrow.
-- Can be used to emulate Applicative <*> like usage:
--
-- @
-- foo :: Appplicative f => f a -> f b -> f (a, b)
-- (,) <$> a <*> b
-- @
--
-- The arrow version is:
--
-- @
-- foo :: Arrow p => p x a -> p x b -> p x (a, b)
-- arr (const (,)) >*> a >*> b
-- @
(>*>) :: Arrow p => p a (b -> c)
    -> p a b
    -> p a c
af >*> ab = af &&& ab >>^ (fst <*> snd)

-- | precomposition with a pure value
(<<^=) :: Arrow a => a c d -> c -> a x d
p <<^= v = p <<^ const v

-- | postcomposition with a pure value
(>>^=) :: Arrow a => a b c -> d -> a b d
p >>^= v = p >>^ const v

-- | postcomposition with a pure value (right-to-left variant)
(=^<<) :: Arrow a => d -> a b c -> a b d
v =^<< p = const v ^<< p

-- | precomposition with a pure value (right-to-left variant)
(=^>>) :: Arrow a => c -> a c d -> a x d
v =^>> p = const v ^>> p